Multiple controllers: Select active controller and set default controller (#3169)

* initial commit - not cleanup yet, not usable with imGUI

* Ugly solution to working with ImGUI

* Populate the default controller labels

* Add remove default button

* missing tr calls

* edit imgui flag after updating

* Refactor

* Update sirit
This commit is contained in:
rainmakerv2 2025-07-31 02:37:45 +08:00 committed by GitHub
parent 35132d9fdc
commit c924c20575
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 515 additions and 255 deletions

View File

@ -57,6 +57,7 @@ static int specialPadClass = 1;
static bool isMotionControlsEnabled = true;
static bool useUnifiedInputConfig = true;
static std::string micDevice = "Default Device";
static std::string defaultControllerID = "";
// These two entries aren't stored in the config
static bool overrideControllerColor = false;
@ -612,6 +613,14 @@ void setPSNSignedIn(bool sign) {
isPSNSignedIn = sign;
}
std::string getDefaultControllerID() {
return defaultControllerID;
}
void setDefaultControllerID(std::string id) {
defaultControllerID = id;
}
void load(const std::filesystem::path& path) {
// If the configuration file does not exist, create it and return
std::error_code error;
@ -656,6 +665,7 @@ void load(const std::filesystem::path& path) {
isConnectedToNetwork =
toml::find_or<bool>(general, "isConnectedToNetwork", isConnectedToNetwork);
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", chooseHomeTab);
defaultControllerID = toml::find_or<std::string>(general, "defaultControllerID", "");
}
if (data.contains("Input")) {
@ -837,6 +847,7 @@ void save(const std::filesystem::path& path) {
data["General"]["compatibilityEnabled"] = compatibilityData;
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
data["General"]["isConnectedToNetwork"] = isConnectedToNetwork;
data["General"]["defaultControllerID"] = defaultControllerID;
data["Input"]["cursorState"] = cursorState;
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
data["Input"]["useSpecialPad"] = useSpecialPad;

View File

@ -107,6 +107,8 @@ bool isDevKitConsole(); // no set
bool vkValidationGpuEnabled(); // no set
bool getIsMotionControlsEnabled();
void setIsMotionControlsEnabled(bool use);
std::string getDefaultControllerID();
void setDefaultControllerID(std::string id);
// TODO
bool GetLoadGameSizeEnabled();

View File

@ -6,7 +6,9 @@
#include <imgui.h>
#include "common/config.h"
#include "core/debug_state.h"
#include "core/memory.h"
#include "imgui_impl_sdl3.h"
#include "input/controller.h"
// SDL
#include <SDL3/SDL.h>
@ -730,18 +732,29 @@ static void UpdateGamepads() {
ImGuiIO& io = ImGui::GetIO();
SdlData* bd = GetBackendData();
// Update list of gamepads to use
if (bd->want_update_gamepads_list && bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) {
CloseGamepads();
int sdl_gamepads_count = 0;
const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count);
for (int n = 0; n < sdl_gamepads_count; n++)
if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) {
bd->gamepads.push_back(gamepad);
if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst)
break;
}
auto memory = Core::Memory::Instance();
auto controller = Common::Singleton<Input::GameController>::Instance();
auto engine = controller->GetEngine();
SDL_Gamepad* SDLGamepad = engine->m_gamepad;
if (SDLGamepad) {
bd->gamepads.push_back(SDLGamepad);
bd->want_update_gamepads_list = false;
} else {
// Update list of gamepads to use
if (bd->want_update_gamepads_list &&
bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) {
CloseGamepads();
int sdl_gamepads_count = 0;
const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count);
for (int n = 0; n < sdl_gamepads_count; n++)
if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) {
bd->gamepads.push_back(gamepad);
if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst)
break;
}
bd->want_update_gamepads_list = false;
}
}
// FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.

View File

@ -8,6 +8,8 @@
#include "core/libraries/pad/pad.h"
#include "input/controller.h"
static std::string SelectedGamepad = "";
namespace Input {
using Libraries::Pad::OrbisPadButtonDataOffset;
@ -324,3 +326,48 @@ u32 GameController::Poll() {
}
} // namespace Input
namespace GamepadSelect {
int GetDefaultGamepad(SDL_JoystickID* gamepadIDs, int gamepadCount) {
char GUIDbuf[33];
if (Config::getDefaultControllerID() != "") {
for (int i = 0; i < gamepadCount; i++) {
SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepadIDs[i]), GUIDbuf, 33);
std::string currentGUID = std::string(GUIDbuf);
if (currentGUID == Config::getDefaultControllerID()) {
return i;
}
}
}
return -1;
}
int GetIndexfromGUID(SDL_JoystickID* gamepadIDs, int gamepadCount, std::string GUID) {
char GUIDbuf[33];
for (int i = 0; i < gamepadCount; i++) {
SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepadIDs[i]), GUIDbuf, 33);
std::string currentGUID = std::string(GUIDbuf);
if (currentGUID == GUID) {
return i;
}
}
return -1;
}
std::string GetGUIDString(SDL_JoystickID* gamepadIDs, int index) {
char GUIDbuf[33];
SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepadIDs[index]), GUIDbuf, 33);
std::string GUID = std::string(GUIDbuf);
return GUID;
}
std::string GetSelectedGamepad() {
return SelectedGamepad;
}
void SetSelectedGamepad(std::string GUID) {
SelectedGamepad = GUID;
}
} // namespace GamepadSelect

View File

@ -6,6 +6,7 @@
#include <algorithm>
#include <memory>
#include <mutex>
#include <SDL3/SDL_gamepad.h>
#include "common/types.h"
#include "core/libraries/pad/pad.h"
@ -55,6 +56,7 @@ public:
virtual State ReadState() = 0;
virtual float GetAccelPollRate() const = 0;
virtual float GetGyroPollRate() const = 0;
SDL_Gamepad* m_gamepad;
};
inline int GetAxis(int min, int max, int value) {
@ -127,3 +129,12 @@ private:
};
} // namespace Input
namespace GamepadSelect {
int GetIndexfromGUID(SDL_JoystickID* gamepadIDs, int gamepadCount, std::string GUID);
std::string GetGUIDString(SDL_JoystickID* gamepadIDs, int index);
std::string GetSelectedGamepad();
void SetSelectedGamepad(std::string GUID);
} // namespace GamepadSelect

View File

@ -9,6 +9,7 @@
#include "common/path_util.h"
#include "control_settings.h"
#include "input/input_handler.h"
#include "sdl_window.h"
#include "ui_control_settings.h"
ControlSettings::ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, bool isGameRunning,
@ -21,7 +22,6 @@ ControlSettings::ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, b
if (!GameRunning) {
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
SDL_InitSubSystem(SDL_INIT_EVENTS);
CheckGamePad();
} else {
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
}
@ -29,6 +29,7 @@ ControlSettings::ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, b
AddBoxItems();
SetUIValuestoMappings();
UpdateLightbarColor();
CheckGamePad();
installEventFilter(this);
ButtonsList = {ui->CrossButton,
@ -118,6 +119,28 @@ ControlSettings::ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, b
[this]() { CheckMapping(MappingButton); });
connect(this, &ControlSettings::AxisChanged, this,
[this]() { ConnectAxisInputs(MappingButton); });
connect(ui->ActiveGamepadBox, &QComboBox::currentIndexChanged, this,
&ControlSettings::ActiveControllerChanged);
connect(ui->DefaultGamepadButton, &QPushButton::clicked, this, [this]() {
ui->DefaultGamepadName->setText(ui->ActiveGamepadBox->currentText());
std::string GUID =
GamepadSelect::GetGUIDString(gamepads, ui->ActiveGamepadBox->currentIndex());
ui->DefaultGamepadLabel->setText(tr("ID: ") + QString::fromStdString(GUID).right(16));
Config::setDefaultControllerID(GUID);
Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml");
QMessageBox::information(this, tr("Default Controller Selected"),
tr("Active controller set as default"));
});
connect(ui->RemoveDefaultGamepadButton, &QPushButton::clicked, this, [this]() {
ui->DefaultGamepadName->setText(tr("No default selected"));
ui->DefaultGamepadLabel->setText(tr("n/a"));
Config::setDefaultControllerID("");
Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml");
QMessageBox::information(this, tr("Default Controller Removed"),
tr("Default controller setting removed"));
});
RemapWrapper = SdlEventWrapper::Wrapper::GetInstance();
SdlEventWrapper::Wrapper::wrapperActive = true;
@ -639,39 +662,91 @@ void ControlSettings::UpdateLightbarColor() {
ui->LightbarColorFrame->setStyleSheet(colorstring);
}
void ControlSettings::CheckGamePad() {
if (GameRunning)
return;
void ControlSettings::ActiveControllerChanged(int value) {
GamepadSelect::SetSelectedGamepad(GamepadSelect::GetGUIDString(gamepads, value));
QString GUID = QString::fromStdString(GamepadSelect::GetSelectedGamepad()).right(16);
ui->ActiveGamepadLabel->setText("ID: " + GUID);
if (gamepad) {
SDL_CloseGamepad(gamepad);
gamepad = nullptr;
}
int gamepad_count;
SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count);
if (!gamepads) {
LOG_ERROR(Input, "Cannot get gamepad list: {}", SDL_GetError());
return;
}
if (gamepad_count == 0) {
LOG_INFO(Input, "No gamepad found!");
SDL_free(gamepads);
return;
}
LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count);
gamepad = SDL_OpenGamepad(gamepads[0]);
gamepad = SDL_OpenGamepad(gamepads[value]);
if (!gamepad) {
LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError());
SDL_free(gamepads);
return;
LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError());
}
}
void ControlSettings::CheckGamePad() {
if (gamepad) {
SDL_CloseGamepad(gamepad);
gamepad = nullptr;
}
SDL_free(gamepads);
gamepads = SDL_GetGamepads(&gamepad_count);
if (!gamepads) {
LOG_ERROR(Input, "Cannot get gamepad list: {}", SDL_GetError());
}
QString defaultGUID = "";
int defaultIndex =
GamepadSelect::GetIndexfromGUID(gamepads, gamepad_count, Config::getDefaultControllerID());
int activeIndex = GamepadSelect::GetIndexfromGUID(gamepads, gamepad_count,
GamepadSelect::GetSelectedGamepad());
if (!GameRunning) {
if (activeIndex != -1) {
gamepad = SDL_OpenGamepad(gamepads[activeIndex]);
} else if (defaultIndex != -1) {
gamepad = SDL_OpenGamepad(gamepads[defaultIndex]);
} else {
LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count);
gamepad = SDL_OpenGamepad(gamepads[0]);
}
if (!gamepad) {
LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError());
}
}
if (!gamepads || gamepad_count == 0) {
ui->ActiveGamepadBox->addItem("No gamepads detected");
ui->ActiveGamepadBox->setCurrentIndex(0);
return;
} else {
for (int i = 0; i < gamepad_count; i++) {
QString name = SDL_GetGamepadNameForID(gamepads[i]);
ui->ActiveGamepadBox->addItem(QString("%1: %2").arg(QString::number(i + 1), name));
}
}
if (defaultIndex != -1) {
defaultGUID =
QString::fromStdString(GamepadSelect::GetGUIDString(gamepads, defaultIndex)).right(16);
ui->DefaultGamepadName->setText(SDL_GetGamepadNameForID(gamepads[defaultIndex]));
ui->DefaultGamepadLabel->setText(tr("ID: ") + defaultGUID);
} else {
ui->DefaultGamepadName->setText("Default controller not connected");
ui->DefaultGamepadLabel->setText(tr("n/a"));
}
if (activeIndex != -1) {
QString GUID =
QString::fromStdString(GamepadSelect::GetGUIDString(gamepads, activeIndex)).right(16);
ui->ActiveGamepadLabel->setText(tr("ID: ") + GUID);
ui->ActiveGamepadBox->setCurrentIndex(activeIndex);
} else if (defaultIndex != -1) {
ui->ActiveGamepadLabel->setText(defaultGUID);
ui->ActiveGamepadBox->setCurrentIndex(defaultIndex);
} else {
QString GUID = QString::fromStdString(GamepadSelect::GetGUIDString(gamepads, 0)).right(16);
ui->ActiveGamepadLabel->setText("ID: " + GUID);
ui->ActiveGamepadBox->setCurrentIndex(0);
}
}
void ControlSettings::DisableMappingButtons() {
@ -914,6 +989,7 @@ void ControlSettings::pollSDLEvents() {
}
if (event.type == SDL_EVENT_GAMEPAD_ADDED) {
ui->ActiveGamepadBox->clear();
CheckGamePad();
}
@ -923,8 +999,12 @@ void ControlSettings::pollSDLEvents() {
void ControlSettings::Cleanup() {
SdlEventWrapper::Wrapper::wrapperActive = false;
if (gamepad)
if (gamepad) {
SDL_CloseGamepad(gamepad);
gamepad = nullptr;
}
SDL_free(gamepads);
if (!GameRunning) {
SDL_Event quitLoop{};
@ -937,6 +1017,9 @@ void ControlSettings::Cleanup() {
SDL_Quit();
} else {
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "0");
SDL_Event checkGamepad{};
checkGamepad.type = SDL_EVENT_CHANGE_CONTROLLER;
SDL_PushEvent(&checkGamepad);
}
}

View File

@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QDialog>
#include <SDL3/SDL.h>
#include <SDL3/SDL_gamepad.h>
@ -29,6 +29,7 @@ private Q_SLOTS:
void CheckMapping(QPushButton*& button);
void StartTimer(QPushButton*& button, bool isButton);
void ConnectAxisInputs(QPushButton*& button);
void ActiveControllerChanged(int value);
private:
std::unique_ptr<Ui::ControlSettings> ui;
@ -59,9 +60,11 @@ private:
bool MappingCompleted = false;
QString mapping;
int MappingTimer;
int gamepad_count;
QTimer* timer;
QPushButton* MappingButton;
SDL_Gamepad* gamepad = nullptr;
SDL_JoystickID* gamepads;
SdlEventWrapper::Wrapper* RemapWrapper;
QFuture<void> Polling;

View File

@ -11,8 +11,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1114</width>
<height>794</height>
<width>1124</width>
<height>847</height>
</rect>
</property>
<property name="windowTitle">
@ -33,8 +33,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1094</width>
<height>744</height>
<width>1104</width>
<height>797</height>
</rect>
</property>
<widget class="QWidget" name="layoutWidget">
@ -42,8 +42,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1091</width>
<height>741</height>
<width>1101</width>
<height>791</height>
</rect>
</property>
<layout class="QHBoxLayout" name="RemapLayout">
@ -246,14 +246,82 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>L1 and L2</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QGroupBox" name="gb_l2">
<property name="title">
<string>L2</string>
</property>
<layout class="QVBoxLayout" name="gb_l2_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="L2Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_l1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>L1</string>
</property>
<layout class="QVBoxLayout" name="gb_l1_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="L1Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
@ -512,7 +580,7 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_middle" stretch="0,0,0,0,0">
<layout class="QVBoxLayout" name="verticalLayout_middle" stretch="0,0,0,0">
<property name="spacing">
<number>0</number>
</property>
@ -598,199 +666,117 @@
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="layout_middle_top">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="layout_system_buttons">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>Active Gamepad</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QGroupBox" name="gb_l1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>L1</string>
</property>
<layout class="QVBoxLayout" name="gb_l1_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="L1Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>133</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="gb_r1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>R1</string>
</property>
<layout class="QVBoxLayout" name="gb_r1_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="R1Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<widget class="QComboBox" name="ActiveGamepadBox">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>false</bold>
</font>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QGroupBox" name="gb_l2">
<property name="title">
<string>L2</string>
</property>
<layout class="QVBoxLayout" name="gb_l2_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="L2Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_start">
<property name="title">
<string>Options</string>
</property>
<layout class="QVBoxLayout" name="gb_start_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="OptionsButton">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_r2">
<property name="title">
<string>R2</string>
</property>
<layout class="QVBoxLayout" name="gb_r2_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="R2Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<widget class="QLabel" name="ActiveGamepadLabel">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Gamepad ID</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>Default Gamepad</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLabel" name="DefaultGamepadName">
<property name="text">
<string>No default selected</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="DefaultGamepadLabel">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>n/a</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<widget class="QPushButton" name="DefaultGamepadButton">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Set Active Gamepad as Default</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="RemoveDefaultGamepadButton">
<property name="font">
<font>
<pointsize>9</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Remove Default Gamepad</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_controller" native="true">
@ -880,20 +866,32 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<widget class="QGroupBox" name="gb_start">
<property name="title">
<string>Options</string>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>133</width>
<height>20</height>
</size>
</property>
</spacer>
<layout class="QVBoxLayout" name="gb_start_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="OptionsButton">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_r3">
@ -1338,13 +1336,84 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>R1 and R2</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QGroupBox" name="gb_r2">
<property name="title">
<string>R2</string>
</property>
<layout class="QVBoxLayout" name="gb_r2_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="R2Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_r1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>R1</string>
</property>
<layout class="QVBoxLayout" name="gb_r1_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="R1Button">
<property name="text">
<string>unmapped</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Maximum</enum>
<enum>QSizePolicy::Policy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>

View File

@ -114,12 +114,31 @@ void SDLInputEngine::Init() {
return;
}
LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count);
m_gamepad = SDL_OpenGamepad(gamepads[0]);
int selectedIndex = GamepadSelect::GetIndexfromGUID(gamepads, gamepad_count,
GamepadSelect::GetSelectedGamepad());
int defaultIndex =
GamepadSelect::GetIndexfromGUID(gamepads, gamepad_count, Config::getDefaultControllerID());
// If user selects a gamepad in the GUI, use that, otherwise try the default
if (!m_gamepad) {
LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError());
SDL_free(gamepads);
return;
if (selectedIndex != -1) {
m_gamepad = SDL_OpenGamepad(gamepads[selectedIndex]);
LOG_INFO(Input, "Opening gamepad selected in GUI.");
} else if (defaultIndex != -1) {
m_gamepad = SDL_OpenGamepad(gamepads[defaultIndex]);
LOG_INFO(Input, "Opening default gamepad.");
} else {
m_gamepad = SDL_OpenGamepad(gamepads[0]);
LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count);
}
}
if (!m_gamepad) {
if (!m_gamepad) {
LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError());
SDL_free(gamepads);
return;
}
}
SDL_Joystick* joystick = SDL_GetGamepadJoystick(m_gamepad);
@ -426,6 +445,9 @@ void WindowSDL::WaitEvent() {
DebugState.PauseGuestThreads();
}
break;
case SDL_EVENT_CHANGE_CONTROLLER:
controller->GetEngine()->Init();
break;
default:
break;
}

View File

@ -9,6 +9,7 @@
#include "string"
#define SDL_EVENT_TOGGLE_FULLSCREEN (SDL_EVENT_USER + 1)
#define SDL_EVENT_TOGGLE_PAUSE (SDL_EVENT_USER + 2)
#define SDL_EVENT_CHANGE_CONTROLLER (SDL_EVENT_USER + 3)
struct SDL_Window;
struct SDL_Gamepad;
@ -27,8 +28,6 @@ public:
State ReadState() override;
private:
SDL_Gamepad* m_gamepad = nullptr;
float m_gyro_poll_rate = 0.0f;
float m_accel_poll_rate = 0.0f;
};