From 06b760e8dd1b8ace5ef7c427c047ca9e911f93b3 Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sun, 17 Oct 2021 18:18:29 +0300 Subject: [PATCH] Player controls: added mouse and game controller remapping. Fixed duplicate button id. --- SpaceCadetPinball/options.cpp | 184 +++++++++++++++++++++++++--------- SpaceCadetPinball/options.h | 40 ++++++-- SpaceCadetPinball/pb.cpp | 121 +++++++++++----------- SpaceCadetPinball/pb.h | 7 +- SpaceCadetPinball/winmain.cpp | 167 ++++++++++++------------------ 5 files changed, 302 insertions(+), 217 deletions(-) diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 4e9f809..00d2ab7 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -13,7 +13,7 @@ optionsStruct options::Options{}; std::map options::settings{}; ControlsStruct options::RebindControls{}; bool options::ShowDialog = false; -const ControlRef* options::ControlWaitingForKey = nullptr; +GameInput* options::ControlWaitingForInput = nullptr; const ControlRef options::Controls[6] { {"Left Flipper", RebindControls.LeftFlipper}, @@ -43,24 +43,50 @@ void options::init() ImGui::EndFrame(); } - Options.KeyDft.LeftFlipper = SDLK_z; - Options.KeyDft.RightFlipper = SDLK_SLASH; - Options.KeyDft.Plunger = SDLK_SPACE; - Options.KeyDft.LeftTableBump = SDLK_x; - Options.KeyDft.RightTableBump = SDLK_PERIOD; - Options.KeyDft.BottomTableBump = SDLK_UP; - Options.Key = Options.KeyDft; + Options.Key = Options.KeyDft = + { + { + {InputTypes::Keyboard, SDLK_z}, + {InputTypes::Mouse, SDL_BUTTON_LEFT}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, + }, + { + {InputTypes::Keyboard, SDLK_SLASH}, + {InputTypes::Mouse, SDL_BUTTON_RIGHT}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, + }, + { + {InputTypes::Keyboard, SDLK_SPACE}, + {InputTypes::Mouse, SDL_BUTTON_MIDDLE}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_A}, + }, + { + {InputTypes::Keyboard, SDLK_x}, + {InputTypes::Mouse, SDL_BUTTON_X1}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, + }, + { + {InputTypes::Keyboard, SDLK_PERIOD}, + {InputTypes::Mouse, SDL_BUTTON_X2}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, + }, + { + {InputTypes::Keyboard, SDLK_UP}, + {InputTypes::Mouse, SDL_BUTTON_X2 + 1}, + {InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_UP}, + }, + }; + GetInput("Left Flipper key", Options.Key.LeftFlipper); + GetInput("Right Flipper key", Options.Key.RightFlipper); + GetInput("Plunger key", Options.Key.Plunger); + GetInput("Left Table Bump key", Options.Key.LeftTableBump); + GetInput("Right Table Bump key", Options.Key.RightTableBump); + GetInput("Bottom Table Bump key", Options.Key.BottomTableBump); Options.Sounds = get_int("Sounds", true); Options.Music = get_int("Music", false); Options.FullScreen = get_int("FullScreen", false); Options.Players = get_int("Players", 1); - Options.Key.LeftFlipper = get_int("Left Flipper key", Options.Key.LeftFlipper); - Options.Key.RightFlipper = get_int("Right Flipper key", Options.Key.RightFlipper); - Options.Key.Plunger = get_int("Plunger key", Options.Key.Plunger); - Options.Key.LeftTableBump = get_int("Left Table Bump key", Options.Key.LeftTableBump); - Options.Key.RightTableBump = get_int("Right Table Bump key", Options.Key.RightTableBump); - Options.Key.BottomTableBump = get_int("Bottom Table Bump key", Options.Key.BottomTableBump); Options.UniformScaling = get_int("Uniform scaling", true); ImGui::GetIO().FontGlobalScale = get_float("UI Scale", 1.0f); Options.Resolution = get_int("Screen Resolution", -1); @@ -83,16 +109,17 @@ void options::init() void options::uninit() { + SetInput("Left Flipper key", Options.Key.LeftFlipper); + SetInput("Right Flipper key", Options.Key.RightFlipper); + SetInput("Plunger key", Options.Key.Plunger); + SetInput("Left Table Bump key", Options.Key.LeftTableBump); + SetInput("Right Table Bump key", Options.Key.RightTableBump); + SetInput("Bottom Table Bump key", Options.Key.BottomTableBump); + set_int("Sounds", Options.Sounds); set_int("Music", Options.Music); set_int("FullScreen", Options.FullScreen); set_int("Players", Options.Players); - set_int("Left Flipper key", Options.Key.LeftFlipper); - set_int("Right Flipper key", Options.Key.RightFlipper); - set_int("Plunger key", Options.Key.Plunger); - set_int("Left Table Bump key", Options.Key.LeftTableBump); - set_int("Right Table Bump key", Options.Key.RightTableBump); - set_int("Bottom Table Bump key", Options.Key.BottomTableBump); set_int("Screen Resolution", Options.Resolution); set_int("Uniform scaling", Options.UniformScaling); set_float("UI Scale", ImGui::GetIO().FontGlobalScale); @@ -137,6 +164,28 @@ void options::set_float(LPCSTR lpValueName, float data) SetSetting(lpValueName, std::to_string(data)); } +void options::GetInput(const std::string& rowName, GameInput (&defaultValues)[3]) +{ + for (auto i = 0u; i <= 2; i++) + { + auto name = rowName + " " + std::to_string(i); + auto inputType = static_cast(get_int((name + " type").c_str(), -1)); + auto input = get_int((name + " input").c_str(), -1); + if (inputType <= InputTypes::GameController && input != -1) + defaultValues[i] = {inputType, input}; + } +} + +void options::SetInput(const std::string& rowName, GameInput (&values)[3]) +{ + for (auto i = 0u; i <= 2; i++) + { + auto input = values[i]; + auto name = rowName + " " + std::to_string(i); + set_int((name + " type").c_str(), static_cast(input.Type)); + set_int((name + " input").c_str(), input.Value); + } +} void options::toggle(Menu1 uIDCheckItem) { @@ -203,16 +252,20 @@ void options::toggle(Menu1 uIDCheckItem) } } -void options::KeyDown(int key) +void options::InputDown(GameInput input) { - if (ControlWaitingForKey) + if (ControlWaitingForInput) { // Skip function keys, just in case. - if (key < SDLK_F1 || key > SDLK_F12) - { - ControlWaitingForKey->Option = key; - ControlWaitingForKey = nullptr; - } + if (input.Type == InputTypes::Keyboard && input.Value >= SDLK_F1 && input.Value <= SDLK_F12) + return; + + // Start is reserved for pause + if (input.Type == InputTypes::GameController && input.Value == SDL_CONTROLLER_BUTTON_START) + return; + + *ControlWaitingForInput = input; + ControlWaitingForInput = nullptr; } } @@ -220,7 +273,7 @@ void options::ShowControlDialog() { if (!ShowDialog) { - ControlWaitingForKey = nullptr; + ControlWaitingForInput = nullptr; RebindControls = Options.Key; ShowDialog = true; } @@ -228,10 +281,20 @@ void options::ShowControlDialog() void options::RenderControlDialog() { + static const char* mouseButtons[] + { + nullptr, + "Mouse Left", + "Mouse Middle", + "Mouse Right", + "Mouse X1", + "Mouse X2", + }; + if (!ShowDialog) return; - ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{500, 400}); + ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{550, 450}); if (ImGui::Begin("3D Pinball: Player Controls", &ShowDialog)) { ImGui::TextUnformatted("Instructions"); @@ -241,39 +304,70 @@ void options::RenderControlDialog() "To change game controls, click the control button, press the new key, and then choose OK."); ImGui::TextWrapped( "To restore 3D Pinball to its original settings, choose Default, and then choose OK."); - ImGui::TextWrapped("Original warns against binding the same key to multiple controls, but does not forbid it."); ImGui::Spacing(); ImGui::TextUnformatted("Control Options"); - ImGui::Separator(); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{5, 10}); - if (ImGui::BeginTable("Controls", 2, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) + if (ImGui::BeginTable("Controls", 4, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { - for (auto& ctrl : Controls) + ImGui::TableSetupColumn("Control"); + ImGui::TableSetupColumn("Binding 1"); + ImGui::TableSetupColumn("Binding 2"); + ImGui::TableSetupColumn("Binding 3"); + ImGui::TableHeadersRow(); + + int index = 0; + for (auto& row : Controls) { ImGui::TableNextColumn(); - if (ImGui::BeginTable("Control", 2, ImGuiTableFlags_NoSavedSettings)) + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.5, 0, 0, 1}); + if (ImGui::Button(row.Name)) { - ImGui::TableNextColumn(); - ImGui::TextWrapped("%s", ctrl.Name); + for (auto i = 0u; i <= 2; i++) + row.Option[i] = {}; + } + ImGui::PopStyleColor(1); + for (auto i = 0u; i <= 2; i++) + { + auto& ctrl = row.Option[i]; ImGui::TableNextColumn(); - if (ControlWaitingForKey == &ctrl) + if (ControlWaitingForInput == &ctrl) { ImGui::Button("Press the key", ImVec2(-1, 0)); } else { - auto keyName = SDL_GetKeyName(ctrl.Option); - if (!keyName[0]) - keyName = "Unknown key"; - if (ImGui::Button(keyName, ImVec2(-1, 0))) + std::string tmp; + const char* keyName; + switch (ctrl.Type) { - ControlWaitingForKey = &ctrl; + case InputTypes::Keyboard: + keyName = SDL_GetKeyName(ctrl.Value); + break; + case InputTypes::Mouse: + if (ctrl.Value >= SDL_BUTTON_LEFT && ctrl.Value <= SDL_BUTTON_X2) + keyName = mouseButtons[ctrl.Value]; + else + keyName = (tmp += "Mouse " + std::to_string(ctrl.Value)).c_str(); + break; + case InputTypes::GameController: + keyName = SDL_GameControllerGetStringForButton( + static_cast(ctrl.Value)); + break; + case InputTypes::None: + default: + keyName = "Unused"; + } + if (!keyName || !keyName[0]) + keyName = "Unknown key"; + if (ImGui::Button((std::string{keyName} + "##" + std::to_string(index++)).c_str(), + ImVec2(-1, 0))) + { + ControlWaitingForInput = &ctrl; } } - ImGui::EndTable(); } } ImGui::EndTable(); @@ -297,14 +391,14 @@ void options::RenderControlDialog() if (ImGui::Button("Default")) { RebindControls = Options.KeyDft; - ControlWaitingForKey = nullptr; + ControlWaitingForInput = nullptr; } } ImGui::End(); ImGui::PopStyleVar(); if (!ShowDialog) - ControlWaitingForKey = nullptr; + ControlWaitingForInput = nullptr; } void options::MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line) diff --git a/SpaceCadetPinball/options.h b/SpaceCadetPinball/options.h index 734100c..5578cb6 100644 --- a/SpaceCadetPinball/options.h +++ b/SpaceCadetPinball/options.h @@ -28,14 +28,33 @@ enum class Menu1:int WindowLinearFilter = 601, }; +enum class InputTypes: unsigned +{ + None = 0, + Keyboard = 1, + Mouse = 2, + GameController = 3, +}; + +struct GameInput +{ + InputTypes Type; + int Value; + + bool operator==(const GameInput& other) const + { + return Type == other.Type && Value == other.Value; + } +}; + struct ControlsStruct { - int LeftFlipper; - int RightFlipper; - int Plunger; - int LeftTableBump; - int RightTableBump; - int BottomTableBump; + GameInput LeftFlipper[3]; + GameInput RightFlipper[3]; + GameInput Plunger[3]; + GameInput LeftTableBump[3]; + GameInput RightTableBump[3]; + GameInput BottomTableBump[3]; }; struct optionsStruct @@ -59,7 +78,7 @@ struct optionsStruct struct ControlRef { const char* Name; - int& Option; + GameInput (&Option)[3]; }; @@ -81,16 +100,19 @@ public: static void set_string(LPCSTR lpValueName, LPCSTR value); static float get_float(LPCSTR lpValueName, float defaultValue); static void set_float(LPCSTR lpValueName, float data); + static void GetInput(const std::string& rowName, GameInput (&defaultValues)[3]); + static void SetInput(const std::string& rowName, GameInput (&values)[3]); static void toggle(Menu1 uIDCheckItem); - static void KeyDown(int key); + static void InputDown(GameInput input); static void ShowControlDialog(); static void RenderControlDialog(); + static bool WaitingForInput() { return ControlWaitingForInput != nullptr; } private: static std::map settings; static ControlsStruct RebindControls; static bool ShowDialog; static const ControlRef Controls[6]; - static const ControlRef* ControlWaitingForKey; + static GameInput* ControlWaitingForInput; static void MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); static void* MyUserData_ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 0977fb0..95f45e5 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -360,86 +360,83 @@ void pb::loose_focus() MainTable->Message(1010, time_now); } -void pb::keyup(int key) +void pb::InputUp(GameInput input) { - if (game_mode == 1 && !winmain::single_step && !demo_mode) + if (game_mode != 1 || winmain::single_step || demo_mode) + return; + + if (AnyBindingMatchesInput(options::Options.Key.LeftFlipper, input)) { - if (key == options::Options.Key.LeftFlipper) - { - MainTable->Message(1001, time_now); - } - else if (key == options::Options.Key.RightFlipper) - { - MainTable->Message(1003, time_now); - } - else if (key == options::Options.Key.Plunger) - { - MainTable->Message(1005, time_now); - } - else if (key == options::Options.Key.LeftTableBump) - { - nudge::un_nudge_right(0, nullptr); - } - else if (key == options::Options.Key.RightTableBump) - { - nudge::un_nudge_left(0, nullptr); - } - else if (key == options::Options.Key.BottomTableBump) - { - nudge::un_nudge_up(0, nullptr); - } + MainTable->Message(1001, time_now); + } + if (AnyBindingMatchesInput(options::Options.Key.RightFlipper, input)) + { + MainTable->Message(1003, time_now); + } + if (AnyBindingMatchesInput(options::Options.Key.Plunger, input)) + { + MainTable->Message(1005, time_now); + } + if (AnyBindingMatchesInput(options::Options.Key.LeftTableBump, input)) + { + nudge::un_nudge_right(0, nullptr); + } + if (AnyBindingMatchesInput(options::Options.Key.RightTableBump, input)) + { + nudge::un_nudge_left(0, nullptr); + } + if (AnyBindingMatchesInput(options::Options.Key.BottomTableBump, input)) + { + nudge::un_nudge_up(0, nullptr); } } -void pb::keydown(int key) +void pb::InputDown(GameInput input) { - options::KeyDown(key); + options::InputDown(input); if (winmain::single_step || demo_mode) return; + if (game_mode != 1) { mode_countdown(-1); return; } - control::pbctrl_bdoor_controller(static_cast(key)); - if (key == options::Options.Key.LeftFlipper) + + if (input.Type == InputTypes::Keyboard) + control::pbctrl_bdoor_controller(static_cast(input.Value)); + + if (AnyBindingMatchesInput(options::Options.Key.LeftFlipper, input)) { MainTable->Message(1000, time_now); - return; } - if (key == options::Options.Key.RightFlipper) + if (AnyBindingMatchesInput(options::Options.Key.RightFlipper, input)) { MainTable->Message(1002, time_now); } - else + if (AnyBindingMatchesInput(options::Options.Key.Plunger, input)) { - if (key == options::Options.Key.Plunger) - { - MainTable->Message(1004, time_now); - return; - } - if (key == options::Options.Key.LeftTableBump) - { - if (!MainTable->TiltLockFlag) - nudge::nudge_right(); - return; - } - if (key == options::Options.Key.RightTableBump) - { - if (!MainTable->TiltLockFlag) - nudge::nudge_left(); - return; - } - if (key == options::Options.Key.BottomTableBump) - { - if (!MainTable->TiltLockFlag) - nudge::nudge_up(); - return; - } + MainTable->Message(1004, time_now); } - if (cheat_mode) + if (AnyBindingMatchesInput(options::Options.Key.LeftTableBump, input)) { - switch (key) + if (!MainTable->TiltLockFlag) + nudge::nudge_right(); + } + if (AnyBindingMatchesInput(options::Options.Key.RightTableBump, input)) + { + if (!MainTable->TiltLockFlag) + nudge::nudge_left(); + } + if (AnyBindingMatchesInput(options::Options.Key.BottomTableBump, input)) + { + if (!MainTable->TiltLockFlag) + nudge::nudge_up(); + } + + if (cheat_mode && input.Type == InputTypes::Keyboard) + { + switch (input.Value) { case 'b': TBall* ball; @@ -648,3 +645,11 @@ void pb::PushCheat(const std::string& cheat) for (auto ch : cheat) control::pbctrl_bdoor_controller(ch); } + +bool pb::AnyBindingMatchesInput(GameInput (&options)[3], GameInput key) +{ + for (auto& option : options) + if (key == option) + return true; + return false; +} diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index 81b2e78..0139db2 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -1,6 +1,7 @@ #pragma once #include "high_score.h" +struct GameInput; class TPinballTable; class DatFile; class TBall; @@ -54,8 +55,8 @@ public: static void window_size(int* width, int* height); static void pause_continue(); static void loose_focus(); - static void keyup(int key); - static void keydown(int key); + static void InputUp(GameInput input); + static void InputDown(GameInput input); static int mode_countdown(int time); static void launch_ball(); static void end_game(); @@ -66,4 +67,6 @@ public: static void PushCheat(const std::string& cheat); private: static int demo_mode, mode_countdown_; + + static bool AnyBindingMatchesInput(GameInput (&options)[3], GameInput key); }; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index eb154a2..cef4dbe 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -218,7 +218,7 @@ int winmain::WinMain(LPCSTR lpCmdLine) float dx = (last_mouse_x - x) / static_cast(w); float dy = (y - last_mouse_y) / static_cast(h); pb::ballset(dx, dy); - + SDL_WarpMouseInWindow(window, last_mouse_x, last_mouse_y); // Mouse warp does not work over remote desktop or in some VMs @@ -563,7 +563,7 @@ int winmain::event_handler(const SDL_Event* event) { ImGui_ImplSDL2_ProcessEvent(event); - if (ImIO->WantCaptureMouse) + if (ImIO->WantCaptureMouse && !options::WaitingForInput()) { if (mouse_down) { @@ -600,11 +600,11 @@ int winmain::event_handler(const SDL_Event* event) return_value = 0; return 0; case SDL_KEYUP: - pb::keyup(event->key.keysym.sym); + pb::InputUp({InputTypes::Keyboard, event->key.keysym.sym}); break; case SDL_KEYDOWN: if (!event->key.repeat) - pb::keydown(event->key.keysym.sym); + pb::InputDown({InputTypes::Keyboard, event->key.keysym.sym}); switch (event->key.keysym.sym) { case SDLK_ESCAPE: @@ -664,51 +664,47 @@ int winmain::event_handler(const SDL_Event* event) } break; case SDL_MOUSEBUTTONDOWN: - switch (event->button.button) { - case SDL_BUTTON_LEFT: - if (pb::cheat_mode) + bool noInput = false; + switch (event->button.button) { - mouse_down = 1; - last_mouse_x = event->button.x; - last_mouse_y = event->button.y; - SDL_SetWindowGrab(MainWindow, SDL_TRUE); + case SDL_BUTTON_LEFT: + if (pb::cheat_mode) + { + mouse_down = 1; + last_mouse_x = event->button.x; + last_mouse_y = event->button.y; + SDL_SetWindowGrab(MainWindow, SDL_TRUE); + noInput = true; + } + break; + default: + break; } - else - pb::keydown(Options.Key.LeftFlipper); - break; - case SDL_BUTTON_RIGHT: - if (!pb::cheat_mode) - pb::keydown(Options.Key.RightFlipper); - break; - case SDL_BUTTON_MIDDLE: - pb::keydown(Options.Key.Plunger); - break; - default: - break; + + if (!noInput) + pb::InputDown({InputTypes::Mouse, event->button.button}); } break; case SDL_MOUSEBUTTONUP: - switch (event->button.button) { - case SDL_BUTTON_LEFT: - if (mouse_down) + bool noInput = false; + switch (event->button.button) { - mouse_down = 0; - SDL_SetWindowGrab(MainWindow, SDL_FALSE); + case SDL_BUTTON_LEFT: + if (mouse_down) + { + mouse_down = 0; + SDL_SetWindowGrab(MainWindow, SDL_FALSE); + noInput = true; + } + break; + default: + break; } - if (!pb::cheat_mode) - pb::keyup(Options.Key.LeftFlipper); - break; - case SDL_BUTTON_RIGHT: - if (!pb::cheat_mode) - pb::keyup(Options.Key.RightFlipper); - break; - case SDL_BUTTON_MIDDLE: - pb::keyup(Options.Key.Plunger); - break; - default: - break; + + if (!noInput) + pb::InputUp({InputTypes::Mouse, event->button.button}); } break; case SDL_WINDOWEVENT: @@ -741,69 +737,34 @@ int winmain::event_handler(const SDL_Event* event) default: ; } break; - case SDL_JOYDEVICEADDED: - if (SDL_IsGameController(event->jdevice.which)) - { - SDL_GameControllerOpen(event->jdevice.which); - } - break; - case SDL_JOYDEVICEREMOVED: - { - SDL_GameController *controller = SDL_GameControllerFromInstanceID(event->jdevice.which); - if (controller) - { - SDL_GameControllerClose(controller); - } - } - break; - case SDL_CONTROLLERBUTTONDOWN: - switch (event->cbutton.button) - { - case SDL_CONTROLLER_BUTTON_A: - pb::keydown(Options.Key.Plunger); - break; - case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: - pb::keydown(Options.Key.LeftFlipper); - break; - case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: - pb::keydown(Options.Key.RightFlipper); - break; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - pb::keydown(Options.Key.LeftTableBump); - break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - pb::keydown(Options.Key.RightTableBump); - break; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: - pb::keydown(Options.Key.BottomTableBump); - break; - default: ; - } - break; - case SDL_CONTROLLERBUTTONUP: - switch (event->cbutton.button) - { - case SDL_CONTROLLER_BUTTON_A: - pb::keyup(Options.Key.Plunger); - break; - case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: - pb::keyup(Options.Key.LeftFlipper); - break; - case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: - pb::keyup(Options.Key.RightFlipper); - break; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - pb::keyup(Options.Key.LeftTableBump); - break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - pb::keyup(Options.Key.RightTableBump); - break; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: - pb::keyup(Options.Key.BottomTableBump); - break; - default: ; - } - break; + case SDL_JOYDEVICEADDED: + if (SDL_IsGameController(event->jdevice.which)) + { + SDL_GameControllerOpen(event->jdevice.which); + } + break; + case SDL_JOYDEVICEREMOVED: + { + SDL_GameController* controller = SDL_GameControllerFromInstanceID(event->jdevice.which); + if (controller) + { + SDL_GameControllerClose(controller); + } + } + break; + case SDL_CONTROLLERBUTTONDOWN: + pb::InputDown({InputTypes::GameController, event->cbutton.button}); + switch (event->cbutton.button) + { + case SDL_CONTROLLER_BUTTON_START: + pause(); + break; + default: ; + } + break; + case SDL_CONTROLLERBUTTONUP: + pb::InputUp({InputTypes::GameController, event->cbutton.button}); + break; default: ; }