diff --git a/dist/qt_themes/default/icons/256x256/automap_face_buttons.png b/dist/qt_themes/default/icons/256x256/automap_face_buttons.png new file mode 100644 index 000000000..581192664 Binary files /dev/null and b/dist/qt_themes/default/icons/256x256/automap_face_buttons.png differ diff --git a/dist/qt_themes/default/theme_default.qrc b/dist/qt_themes/default/theme_default.qrc index 90ae777aa..4d035c33c 100644 --- a/dist/qt_themes/default/theme_default.qrc +++ b/dist/qt_themes/default/theme_default.qrc @@ -15,6 +15,7 @@ icons/48x48/sd_card.png icons/128x128/cartridge.png icons/256x256/azahar.png + icons/256x256/automap_face_buttons.png icons/48x48/star.png icons/256x256/plus_folder.png diff --git a/src/citra_qt/configuration/configure_input.cpp b/src/citra_qt/configuration/configure_input.cpp index 196ad8788..6f072a7ad 100644 --- a/src/citra_qt/configuration/configure_input.cpp +++ b/src/citra_qt/configuration/configure_input.cpp @@ -531,9 +531,15 @@ void ConfigureInput::MapFromButton(const Common::ParamPackage& params) { void ConfigureInput::AutoMap() { ui->buttonAutoMap->setEnabled(false); - if (QMessageBox::information(this, tr("Information"), - tr("After pressing OK, press any button on your joystick"), - QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) { + QMessageBox box(this); + box.setWindowTitle(tr("Auto map Controller")); + box.setText(tr("After pressing OK, press the A (right) button on your gamepad")); + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + QPixmap pixmap(QStringLiteral(":/icons/default/256x256/automap_face_buttons.png")); + pixmap = pixmap.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation); + box.setIconPixmap(pixmap); + int result = box.exec(); + if (result == QMessageBox::Cancel) { ui->buttonAutoMap->setEnabled(true); return; } diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 3af010902..3288e6979 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -202,8 +202,8 @@ Common::ParamPackage GetControllerButtonBinds(const Common::ParamPackage& params const auto native_button{static_cast(button)}; const auto engine{params.Get("engine", "")}; if (engine == "sdl") { - return dynamic_cast(sdl.get())->GetSDLControllerButtonBind( - params.Get("guid", "0"), params.Get("port", 0), native_button); + return dynamic_cast(sdl.get())->GetSDLControllerButtonBind(params, + native_button); } #ifdef ENABLE_GCADAPTER if (engine == "gcpad") { diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 8f246f641..29a972f74 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -169,6 +169,27 @@ constexpr std::array + nintendo_to_3ds_mapping = {{ + SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_B, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_Y, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_LEFTSHOULDER, + SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_INVALID, + SDL_CONTROLLER_BUTTON_INVALID, + SDL_CONTROLLER_BUTTON_INVALID, + SDL_CONTROLLER_BUTTON_INVALID, + SDL_CONTROLLER_BUTTON_GUIDE, + SDL_CONTROLLER_BUTTON_INVALID, + }}; const std::map axis_names = { {SDL_CONTROLLER_AXIS_LEFTX, "Left Stick X"}, @@ -249,13 +270,31 @@ std::shared_ptr SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_ return nullptr; } -Common::ParamPackage SDLState::GetSDLControllerButtonBind(const std::string& guid, int port, - Settings::NativeButton::Values button) { +/** + * Return the button binds param package for the button assuming the params passed in is for the + * n3ds "A" button to determine whether this is xbox or nintendo layout. If the passed in button + * is neither A nor B, default to xbox layout as the most common on desktop. + */ +Common::ParamPackage SDLState::GetSDLControllerButtonBind( + const Common::ParamPackage a_button_params, Settings::NativeButton::Values button) { + auto guid = a_button_params.Get("guid", 0); + auto port = a_button_params.Get("port", 0); + auto a_button = a_button_params.Get("button", -1); + auto api = a_button_params.Get("api", "joystick"); + // for xinputs, the "A" or right button would normally register as the B button. But if the + // user is either using a nintendo-layout controller or using xinput but would rather the labels + // match than the icons, they can press the button that appears as "A" and trigger nintendo + // automap + bool is_nintendo_layout = + api == "controller" && a_button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A; + Common::ParamPackage params({{"engine", "sdl"}}); params.Set("guid", guid); params.Set("port", port); - auto mapped_button = xinput_to_3ds_mapping[static_cast(button)]; + auto mapped_button = is_nintendo_layout ? nintendo_to_3ds_mapping[static_cast(button)] + : xinput_to_3ds_mapping[static_cast(button)]; + params.Set("api", "controller"); if (button == Settings::NativeButton::Values::ZL) { params.Set("axis", SDL_CONTROLLER_AXIS_TRIGGERLEFT); diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 7de96c3f0..3331312ce 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h @@ -36,7 +36,7 @@ public: const std::string& guid); std::shared_ptr GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); - Common::ParamPackage GetSDLControllerButtonBind(const std::string& guid, int port, + Common::ParamPackage GetSDLControllerButtonBind(const Common::ParamPackage a_button_params, Settings::NativeButton::Values button); Common::ParamPackage GetSDLControllerAnalogBindByGUID(const std::string& guid, int port, Settings::NativeAnalog::Values analog);