Files

144 lines
4.3 KiB
C++
Raw Permalink Normal View History

2022-07-27 11:25:25 -04:00
#include "input.hpp"
#include "internal.hpp"
#include "magic_enum.hpp"
2025-04-02 19:57:16 -06:00
#include <SDL3/SDL_haptic.h>
#include <SDL3/SDL_version.h>
#include <SDL3/SDL.h>
2022-07-27 11:25:25 -04:00
#include <absl/container/btree_map.h>
#include <absl/container/flat_hash_map.h>
#include <cmath>
using namespace std::string_view_literals;
namespace aurora::input {
Module Log("aurora::input");
2022-07-27 11:25:25 -04:00
absl::flat_hash_map<Uint32, GameController> g_GameControllers;
GameController* get_controller_for_player(uint32_t player) noexcept {
for (auto& [which, controller] : g_GameControllers) {
if (player_index(which) == player) {
return &controller;
}
}
#if 0
/* If we don't have a controller assigned to this port use the first unassigned controller */
if (!g_GameControllers.empty()) {
int32_t availIndex = -1;
GameController* ct = nullptr;
for (auto& controller : g_GameControllers) {
if (player_index(controller.first) == -1) {
availIndex = controller.first;
ct = &controller.second;
break;
}
}
if (availIndex != -1) {
set_player_index(availIndex, player);
return ct;
}
}
#endif
return nullptr;
}
Sint32 get_instance_for_player(uint32_t player) noexcept {
for (const auto& [which, controller] : g_GameControllers) {
if (player_index(which) == player) {
return which;
}
}
return {};
}
2025-04-02 19:57:16 -06:00
SDL_JoystickID add_controller(SDL_JoystickID which) noexcept {
auto* ctrl = SDL_OpenGamepad(which);
2022-07-27 11:25:25 -04:00
if (ctrl != nullptr) {
GameController controller;
controller.m_controller = ctrl;
controller.m_index = which;
2025-04-02 19:57:16 -06:00
controller.m_vid = SDL_GetGamepadVendor(ctrl);
controller.m_pid = SDL_GetGamepadProduct(ctrl);
2022-07-27 11:25:25 -04:00
if (controller.m_vid == 0x05ac /* USB_VENDOR_APPLE */ && controller.m_pid == 3) {
// Ignore Apple TV remote
2025-04-02 19:57:16 -06:00
SDL_CloseGamepad(ctrl);
2022-07-27 11:25:25 -04:00
return -1;
}
2026-03-27 18:44:47 +01:00
controller.m_isGameCube = SDL_GetGamepadType(ctrl) == SDL_GAMEPAD_TYPE_GAMECUBE;
2025-04-02 19:57:16 -06:00
const auto props = SDL_GetGamepadProperties(ctrl);
controller.m_hasRumble = SDL_GetBooleanProperty(props, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, true);
SDL_JoystickID instance = SDL_GetJoystickID(SDL_GetGamepadJoystick(ctrl));
2022-07-27 11:25:25 -04:00
g_GameControllers[instance] = controller;
return instance;
}
return -1;
}
void remove_controller(Uint32 instance) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
2025-04-02 19:57:16 -06:00
SDL_CloseGamepad(g_GameControllers[instance].m_controller);
2022-07-27 11:25:25 -04:00
g_GameControllers.erase(instance);
}
}
bool is_gamecube(Uint32 instance) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
return g_GameControllers[instance].m_isGameCube;
}
return false;
}
int32_t player_index(Uint32 instance) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
2025-04-02 19:57:16 -06:00
return SDL_GetGamepadPlayerIndex(g_GameControllers[instance].m_controller);
2022-07-27 11:25:25 -04:00
}
return -1;
}
void set_player_index(Uint32 instance, Sint32 index) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
2025-04-02 19:57:16 -06:00
SDL_SetGamepadPlayerIndex(g_GameControllers[instance].m_controller, index);
2022-07-27 11:25:25 -04:00
}
}
std::string controller_name(Uint32 instance) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
2025-04-02 19:57:16 -06:00
const auto* name = SDL_GetGamepadName(g_GameControllers[instance].m_controller);
2022-07-27 11:25:25 -04:00
if (name != nullptr) {
return {name};
}
}
return {};
}
bool controller_has_rumble(Uint32 instance) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
return g_GameControllers[instance].m_hasRumble;
}
return false;
}
void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity,
uint16_t duration_ms) noexcept {
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
2025-04-02 19:57:16 -06:00
SDL_RumbleGamepad(g_GameControllers[instance].m_controller, low_freq_intensity, high_freq_intensity, duration_ms);
2022-07-27 11:25:25 -04:00
}
}
uint32_t controller_count() noexcept { return g_GameControllers.size(); }
2023-01-21 19:48:26 -08:00
void initialize() noexcept {
/* Make sure we initialize everything input related now, this will automatically add all of the connected controllers
* as expected */
2025-04-02 19:57:16 -06:00
ASSERT(SDL_Init(SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD), "Failed to initialize SDL subsystems: {}",
SDL_GetError());
2023-01-21 19:48:26 -08:00
}
2022-07-27 11:25:25 -04:00
} // namespace aurora::input