mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 09:35:40 +00:00
Frontend: Dynamic button mapping based on controller type
This commit is contained in:
parent
c65279f944
commit
32d8b4dc84
|
@ -43,10 +43,15 @@ std::optional<s32> Controller::GetButtonCodeByName(ControllerType type, std::str
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ControllerType::DigitalController:
|
case ControllerType::DigitalController:
|
||||||
return DigitalController::GetButtonCodeByName(button_name);
|
return DigitalController::StaticGetButtonCodeByName(button_name);
|
||||||
|
|
||||||
case ControllerType::None:
|
case ControllerType::None:
|
||||||
default:
|
default:
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<s32> Controller::GetButtonCodeByName(std::string_view button_name) const
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,12 @@ public:
|
||||||
Controller();
|
Controller();
|
||||||
virtual ~Controller();
|
virtual ~Controller();
|
||||||
|
|
||||||
|
/// Returns the type of controller.
|
||||||
|
virtual ControllerType GetType() const = 0;
|
||||||
|
|
||||||
|
/// Gets the integer code for a button in the specified controller type.
|
||||||
|
virtual std::optional<s32> GetButtonCodeByName(std::string_view button_name) const;
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
virtual bool DoState(StateWrapper& sw);
|
virtual bool DoState(StateWrapper& sw);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,16 @@ DigitalController::DigitalController() = default;
|
||||||
|
|
||||||
DigitalController::~DigitalController() = default;
|
DigitalController::~DigitalController() = default;
|
||||||
|
|
||||||
|
ControllerType DigitalController::GetType() const
|
||||||
|
{
|
||||||
|
return ControllerType::DigitalController;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<s32> DigitalController::GetButtonCodeByName(std::string_view button_name) const
|
||||||
|
{
|
||||||
|
return StaticGetButtonCodeByName(button_name);
|
||||||
|
}
|
||||||
|
|
||||||
void DigitalController::SetButtonState(Button button, bool pressed)
|
void DigitalController::SetButtonState(Button button, bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed)
|
if (pressed)
|
||||||
|
@ -81,7 +91,7 @@ std::unique_ptr<DigitalController> DigitalController::Create()
|
||||||
return std::make_unique<DigitalController>();
|
return std::make_unique<DigitalController>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> DigitalController::GetButtonCodeByName(std::string_view button_name)
|
std::optional<s32> DigitalController::StaticGetButtonCodeByName(std::string_view button_name)
|
||||||
{
|
{
|
||||||
#define BUTTON(name) \
|
#define BUTTON(name) \
|
||||||
if (button_name == #name) \
|
if (button_name == #name) \
|
||||||
|
|
|
@ -32,7 +32,10 @@ public:
|
||||||
~DigitalController() override;
|
~DigitalController() override;
|
||||||
|
|
||||||
static std::unique_ptr<DigitalController> Create();
|
static std::unique_ptr<DigitalController> Create();
|
||||||
static std::optional<s32> GetButtonCodeByName(std::string_view button_name);
|
static std::optional<s32> StaticGetButtonCodeByName(std::string_view button_name);
|
||||||
|
|
||||||
|
ControllerType GetType() const override;
|
||||||
|
std::optional<s32> GetButtonCodeByName(std::string_view button_name) const override;
|
||||||
|
|
||||||
void SetButtonState(Button button, bool pressed);
|
void SetButtonState(Button button, bool pressed);
|
||||||
void SetButtonState(s32 button_code, bool pressed);
|
void SetButtonState(s32 button_code, bool pressed);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "YBaseLib/Error.h"
|
#include "YBaseLib/Error.h"
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
#include "core/cdrom.h"
|
#include "core/cdrom.h"
|
||||||
#include "core/digital_controller.h"
|
|
||||||
#include "core/dma.h"
|
#include "core/dma.h"
|
||||||
#include "core/gpu.h"
|
#include "core/gpu.h"
|
||||||
#include "core/host_display.h"
|
#include "core/host_display.h"
|
||||||
|
@ -216,6 +215,12 @@ void SDLHostInterface::UpdateFullscreen()
|
||||||
m_settings.display_fullscreen ? 0 : static_cast<int>(20.0f * ImGui::GetIO().DisplayFramebufferScale.x));
|
m_settings.display_fullscreen ? 0 : static_cast<int>(20.0f * ImGui::GetIO().DisplayFramebufferScale.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLHostInterface::UpdateControllerMapping()
|
||||||
|
{
|
||||||
|
UpdateKeyboardControllerMapping();
|
||||||
|
UpdateControllerControllerMapping();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<SDLHostInterface> SDLHostInterface::Create(const char* filename /* = nullptr */,
|
std::unique_ptr<SDLHostInterface> SDLHostInterface::Create(const char* filename /* = nullptr */,
|
||||||
const char* exp1_filename /* = nullptr */,
|
const char* exp1_filename /* = nullptr */,
|
||||||
const char* save_state_filename /* = nullptr */)
|
const char* save_state_filename /* = nullptr */)
|
||||||
|
@ -257,6 +262,8 @@ std::unique_ptr<SDLHostInterface> SDLHostInterface::Create(const char* filename
|
||||||
|
|
||||||
if (save_state_filename)
|
if (save_state_filename)
|
||||||
intf->LoadState(save_state_filename);
|
intf->LoadState(save_state_filename);
|
||||||
|
|
||||||
|
intf->UpdateControllerMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
intf->UpdateFullscreen();
|
intf->UpdateFullscreen();
|
||||||
|
@ -279,156 +286,6 @@ void SDLHostInterface::ReportMessage(const char* message)
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "DuckStation Information", message, m_window);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "DuckStation Information", message, m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 SDLButtonToHostButton(u32 button)
|
|
||||||
{
|
|
||||||
// SDL left = 1, middle = 2, right = 3 :/
|
|
||||||
switch (button)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
return 0;
|
|
||||||
case 2:
|
|
||||||
return 2;
|
|
||||||
case 3:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool HandleSDLKeyEventForController(const SDL_Event* event, DigitalController* controller)
|
|
||||||
{
|
|
||||||
const bool pressed = (event->type == SDL_KEYDOWN);
|
|
||||||
switch (event->key.keysym.scancode)
|
|
||||||
{
|
|
||||||
case SDL_SCANCODE_KP_8:
|
|
||||||
case SDL_SCANCODE_I:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Triangle, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_KP_2:
|
|
||||||
case SDL_SCANCODE_K:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Cross, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_KP_4:
|
|
||||||
case SDL_SCANCODE_J:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Square, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_KP_6:
|
|
||||||
case SDL_SCANCODE_L:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Circle, pressed);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_W:
|
|
||||||
case SDL_SCANCODE_UP:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Up, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_S:
|
|
||||||
case SDL_SCANCODE_DOWN:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Down, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_A:
|
|
||||||
case SDL_SCANCODE_LEFT:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Left, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_D:
|
|
||||||
case SDL_SCANCODE_RIGHT:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Right, pressed);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_Q:
|
|
||||||
controller->SetButtonState(DigitalController::Button::L1, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_E:
|
|
||||||
controller->SetButtonState(DigitalController::Button::R1, pressed);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_1:
|
|
||||||
controller->SetButtonState(DigitalController::Button::L2, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_3:
|
|
||||||
controller->SetButtonState(DigitalController::Button::R2, pressed);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_RETURN:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Start, pressed);
|
|
||||||
return true;
|
|
||||||
case SDL_SCANCODE_BACKSPACE:
|
|
||||||
controller->SetButtonState(DigitalController::Button::Select, pressed);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void HandleSDLControllerAxisEventForController(const SDL_Event* ev, DigitalController* controller)
|
|
||||||
{
|
|
||||||
// Log_DevPrintf("axis %d %d", ev->caxis.axis, ev->caxis.value);
|
|
||||||
|
|
||||||
static constexpr int deadzone = 8192;
|
|
||||||
const bool negative = (ev->caxis.value < 0);
|
|
||||||
const bool active = (std::abs(ev->caxis.value) >= deadzone);
|
|
||||||
|
|
||||||
if (ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
|
||||||
{
|
|
||||||
controller->SetButtonState(DigitalController::Button::L2, active);
|
|
||||||
}
|
|
||||||
else if (ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
|
||||||
{
|
|
||||||
controller->SetButtonState(DigitalController::Button::R2, active);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DigitalController::Button negative_button, positive_button;
|
|
||||||
if (ev->caxis.axis & 1)
|
|
||||||
{
|
|
||||||
negative_button = DigitalController::Button::Up;
|
|
||||||
positive_button = DigitalController::Button::Down;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
negative_button = DigitalController::Button::Left;
|
|
||||||
positive_button = DigitalController::Button::Right;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->SetButtonState(negative_button, negative && active);
|
|
||||||
controller->SetButtonState(positive_button, !negative && active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void HandleSDLControllerButtonEventForController(const SDL_Event* ev, DigitalController* controller)
|
|
||||||
{
|
|
||||||
// Log_DevPrintf("button %d %s", ev->cbutton.button, ev->cbutton.state == SDL_PRESSED ? "pressed" : "released");
|
|
||||||
|
|
||||||
// For xbox one controller..
|
|
||||||
static constexpr std::pair<SDL_GameControllerButton, DigitalController::Button> button_mapping[] = {
|
|
||||||
{SDL_CONTROLLER_BUTTON_A, DigitalController::Button::Cross},
|
|
||||||
{SDL_CONTROLLER_BUTTON_B, DigitalController::Button::Circle},
|
|
||||||
{SDL_CONTROLLER_BUTTON_X, DigitalController::Button::Square},
|
|
||||||
{SDL_CONTROLLER_BUTTON_Y, DigitalController::Button::Triangle},
|
|
||||||
{SDL_CONTROLLER_BUTTON_BACK, DigitalController::Button::Select},
|
|
||||||
{SDL_CONTROLLER_BUTTON_START, DigitalController::Button::Start},
|
|
||||||
{SDL_CONTROLLER_BUTTON_GUIDE, DigitalController::Button::Start},
|
|
||||||
{SDL_CONTROLLER_BUTTON_LEFTSTICK, DigitalController::Button::L3},
|
|
||||||
{SDL_CONTROLLER_BUTTON_RIGHTSTICK, DigitalController::Button::R3},
|
|
||||||
{SDL_CONTROLLER_BUTTON_LEFTSHOULDER, DigitalController::Button::L1},
|
|
||||||
{SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, DigitalController::Button::R1},
|
|
||||||
{SDL_CONTROLLER_BUTTON_DPAD_UP, DigitalController::Button::Up},
|
|
||||||
{SDL_CONTROLLER_BUTTON_DPAD_DOWN, DigitalController::Button::Down},
|
|
||||||
{SDL_CONTROLLER_BUTTON_DPAD_LEFT, DigitalController::Button::Left},
|
|
||||||
{SDL_CONTROLLER_BUTTON_DPAD_RIGHT, DigitalController::Button::Right}};
|
|
||||||
|
|
||||||
for (const auto& bm : button_mapping)
|
|
||||||
{
|
|
||||||
if (bm.first == ev->cbutton.button)
|
|
||||||
{
|
|
||||||
controller->SetButtonState(bm.second, ev->cbutton.state == SDL_PRESSED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
{
|
{
|
||||||
ImGui_ImplSDL2_ProcessEvent(event);
|
ImGui_ImplSDL2_ProcessEvent(event);
|
||||||
|
@ -482,11 +339,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
{
|
HandleSDLControllerAxisEventForController(event);
|
||||||
DigitalController* controller = static_cast<DigitalController*>(m_system->GetController(0));
|
|
||||||
if (controller)
|
|
||||||
HandleSDLControllerAxisEventForController(event, controller);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_CONTROLLERBUTTONDOWN:
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
@ -498,9 +351,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
m_focus_main_menu_bar = true;
|
m_focus_main_menu_bar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DigitalController* controller = static_cast<DigitalController*>(m_system->GetController(0));
|
HandleSDLControllerButtonEventForController(event);
|
||||||
if (controller)
|
|
||||||
HandleSDLControllerButtonEventForController(event, controller);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -516,8 +367,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
|
void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
|
||||||
{
|
{
|
||||||
const bool repeat = event->key.repeat != 0;
|
const bool repeat = event->key.repeat != 0;
|
||||||
DigitalController* controller = static_cast<DigitalController*>(m_system->GetController(0));
|
if (!repeat && HandleSDLKeyEventForController(event))
|
||||||
if (!repeat && controller && HandleSDLKeyEventForController(event, controller))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const bool pressed = (event->type == SDL_KEYDOWN);
|
const bool pressed = (event->type == SDL_KEYDOWN);
|
||||||
|
@ -605,6 +455,198 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLHostInterface::UpdateKeyboardControllerMapping()
|
||||||
|
{
|
||||||
|
m_keyboard_button_mapping.fill(-1);
|
||||||
|
|
||||||
|
const Controller* controller = m_system->GetController(0);
|
||||||
|
if (controller)
|
||||||
|
{
|
||||||
|
#define SET_BUTTON_MAP(action, name) \
|
||||||
|
m_keyboard_button_mapping[static_cast<int>(action)] = controller->GetButtonCodeByName(name).value_or(-1)
|
||||||
|
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Up, "Up");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Down, "Down");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Left, "Left");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Right, "Right");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Triangle, "Triangle");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Cross, "Cross");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Square, "Square");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Circle, "Circle");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::L1, "L1");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::R1, "R1");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::L2, "L2");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::R2, "R2");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Start, "Start");
|
||||||
|
SET_BUTTON_MAP(KeyboardControllerAction::Select, "Select");
|
||||||
|
|
||||||
|
#undef SET_BUTTON_MAP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLHostInterface::HandleSDLKeyEventForController(const SDL_Event* event)
|
||||||
|
{
|
||||||
|
const bool pressed = (event->type == SDL_KEYDOWN);
|
||||||
|
Controller* controller;
|
||||||
|
|
||||||
|
#define DO_ACTION(action) \
|
||||||
|
if ((controller = m_system->GetController(0)) != nullptr && m_keyboard_button_mapping[static_cast<int>(action)]) \
|
||||||
|
{ \
|
||||||
|
controller->SetButtonState(m_keyboard_button_mapping[static_cast<int>(action)], pressed); \
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event->key.keysym.scancode)
|
||||||
|
{
|
||||||
|
case SDL_SCANCODE_KP_8:
|
||||||
|
case SDL_SCANCODE_I:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Triangle);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_KP_2:
|
||||||
|
case SDL_SCANCODE_K:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Cross);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_KP_4:
|
||||||
|
case SDL_SCANCODE_J:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Square);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_KP_6:
|
||||||
|
case SDL_SCANCODE_L:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Circle);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_W:
|
||||||
|
case SDL_SCANCODE_UP:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Up);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_S:
|
||||||
|
case SDL_SCANCODE_DOWN:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Down);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_A:
|
||||||
|
case SDL_SCANCODE_LEFT:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Left);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_D:
|
||||||
|
case SDL_SCANCODE_RIGHT:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Right);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_Q:
|
||||||
|
DO_ACTION(KeyboardControllerAction::L1);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_E:
|
||||||
|
DO_ACTION(KeyboardControllerAction::R1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_1:
|
||||||
|
DO_ACTION(KeyboardControllerAction::L2);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_3:
|
||||||
|
DO_ACTION(KeyboardControllerAction::R2);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_RETURN:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Start);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_BACKSPACE:
|
||||||
|
DO_ACTION(KeyboardControllerAction::Select);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef DO_ACTION
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLHostInterface::UpdateControllerControllerMapping()
|
||||||
|
{
|
||||||
|
m_controller_button_mapping.fill(-1);
|
||||||
|
|
||||||
|
const Controller* controller = m_system->GetController(0);
|
||||||
|
if (controller)
|
||||||
|
{
|
||||||
|
#define SET_BUTTON_MAP(action, name) \
|
||||||
|
m_controller_button_mapping[static_cast<int>(action)] = controller->GetButtonCodeByName(name).value_or(-1)
|
||||||
|
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_UP, "Up");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_DOWN, "Down");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_LEFT, "Left");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_RIGHT, "Right");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_Y, "Triangle");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_A, "Cross");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_X, "Square");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_B, "Circle");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, "L1");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, "R1");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_LEFTSTICK, "L3");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_RIGHTSTICK, "R3");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_START, "Start");
|
||||||
|
SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_BACK, "Select");
|
||||||
|
|
||||||
|
#undef SET_BUTTON_MAP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLHostInterface::HandleSDLControllerAxisEventForController(const SDL_Event* ev)
|
||||||
|
{
|
||||||
|
// Log_DevPrintf("axis %d %d", ev->caxis.axis, ev->caxis.value);
|
||||||
|
Controller* controller = m_system->GetController(0);
|
||||||
|
if (!controller)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static constexpr int deadzone = 8192;
|
||||||
|
const bool negative = (ev->caxis.value < 0);
|
||||||
|
const bool active = (std::abs(ev->caxis.value) >= deadzone);
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
if (ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
||||||
|
{
|
||||||
|
auto button = controller->GetButtonCodeByName("L2");
|
||||||
|
if (button)
|
||||||
|
controller->SetButtonState(button.value(), active);
|
||||||
|
}
|
||||||
|
else if (ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||||
|
{
|
||||||
|
auto button = controller->GetButtonCodeByName("R2");
|
||||||
|
if (button)
|
||||||
|
controller->SetButtonState(button.value(), active);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SDL_GameControllerButton negative_button, positive_button;
|
||||||
|
if (ev->caxis.axis & 1)
|
||||||
|
{
|
||||||
|
negative_button = SDL_CONTROLLER_BUTTON_DPAD_UP;
|
||||||
|
positive_button = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
negative_button = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
|
||||||
|
positive_button = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_controller_button_mapping[negative_button] >= 0)
|
||||||
|
controller->SetButtonState(m_controller_button_mapping[negative_button], negative && active);
|
||||||
|
if (m_controller_button_mapping[positive_button] >= 0)
|
||||||
|
controller->SetButtonState(m_controller_button_mapping[positive_button], !negative && active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLHostInterface::HandleSDLControllerButtonEventForController(const SDL_Event* ev)
|
||||||
|
{
|
||||||
|
// Log_DevPrintf("button %d %s", ev->cbutton.button, ev->cbutton.state == SDL_PRESSED ? "pressed" : "released");
|
||||||
|
|
||||||
|
Controller* controller = m_system->GetController(0);
|
||||||
|
if (!controller)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_controller_button_mapping[ev->cbutton.button] >= 0)
|
||||||
|
controller->SetButtonState(m_controller_button_mapping[ev->cbutton.button], ev->cbutton.state == SDL_PRESSED);
|
||||||
|
}
|
||||||
|
|
||||||
void SDLHostInterface::DrawImGui()
|
void SDLHostInterface::DrawImGui()
|
||||||
{
|
{
|
||||||
DrawMainMenuBar();
|
DrawMainMenuBar();
|
||||||
|
@ -1285,6 +1327,7 @@ void SDLHostInterface::DoResume()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateControllerMapping();
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
ClearImGuiFocus();
|
ClearImGuiFocus();
|
||||||
}
|
}
|
||||||
|
@ -1304,6 +1347,7 @@ void SDLHostInterface::DoStartDisc()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateControllerMapping();
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
ClearImGuiFocus();
|
ClearImGuiFocus();
|
||||||
}
|
}
|
||||||
|
@ -1319,6 +1363,7 @@ void SDLHostInterface::DoStartBIOS()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateControllerMapping();
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
ClearImGuiFocus();
|
ClearImGuiFocus();
|
||||||
}
|
}
|
||||||
|
@ -1355,6 +1400,7 @@ void SDLHostInterface::DoLoadState(u32 index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateControllerMapping();
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
ClearImGuiFocus();
|
ClearImGuiFocus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include "YBaseLib/Timer.h"
|
#include "YBaseLib/Timer.h"
|
||||||
#include "common/gl/program.h"
|
#include "common/gl/program.h"
|
||||||
#include "common/gl/texture.h"
|
#include "common/gl/texture.h"
|
||||||
#include "core/host_interface.h"
|
|
||||||
#include "core/host_display.h"
|
#include "core/host_display.h"
|
||||||
|
#include "core/host_interface.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
@ -15,6 +15,8 @@
|
||||||
class System;
|
class System;
|
||||||
class AudioStream;
|
class AudioStream;
|
||||||
|
|
||||||
|
class Controller;
|
||||||
|
|
||||||
class SDLHostInterface final : public HostInterface
|
class SDLHostInterface final : public HostInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -32,6 +34,27 @@ public:
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class KeyboardControllerAction
|
||||||
|
{
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Triangle,
|
||||||
|
Cross,
|
||||||
|
Square,
|
||||||
|
Circle,
|
||||||
|
L1,
|
||||||
|
R1,
|
||||||
|
L2,
|
||||||
|
R2,
|
||||||
|
Start,
|
||||||
|
Select,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
using KeyboardControllerActionMap = std::array<s32, static_cast<int>(KeyboardControllerAction::Count)>;
|
||||||
|
|
||||||
static constexpr u32 NUM_QUICK_SAVE_STATES = 10;
|
static constexpr u32 NUM_QUICK_SAVE_STATES = 10;
|
||||||
static constexpr char RESUME_SAVESTATE_FILENAME[] = "savestate_resume.bin";
|
static constexpr char RESUME_SAVESTATE_FILENAME[] = "savestate_resume.bin";
|
||||||
|
|
||||||
|
@ -58,6 +81,7 @@ private:
|
||||||
void QueueSwitchGPURenderer();
|
void QueueSwitchGPURenderer();
|
||||||
void SwitchGPURenderer();
|
void SwitchGPURenderer();
|
||||||
void UpdateFullscreen();
|
void UpdateFullscreen();
|
||||||
|
void UpdateControllerMapping();
|
||||||
|
|
||||||
// We only pass mouse input through if it's grabbed
|
// We only pass mouse input through if it's grabbed
|
||||||
void DrawImGui();
|
void DrawImGui();
|
||||||
|
@ -77,6 +101,13 @@ private:
|
||||||
void HandleSDLEvent(const SDL_Event* event);
|
void HandleSDLEvent(const SDL_Event* event);
|
||||||
void HandleSDLKeyEvent(const SDL_Event* event);
|
void HandleSDLKeyEvent(const SDL_Event* event);
|
||||||
|
|
||||||
|
void UpdateKeyboardControllerMapping();
|
||||||
|
bool HandleSDLKeyEventForController(const SDL_Event* event);
|
||||||
|
|
||||||
|
void UpdateControllerControllerMapping();
|
||||||
|
void HandleSDLControllerAxisEventForController(const SDL_Event* event);
|
||||||
|
void HandleSDLControllerButtonEventForController(const SDL_Event* event);
|
||||||
|
|
||||||
void DrawMainMenuBar();
|
void DrawMainMenuBar();
|
||||||
void DrawQuickSettingsMenu();
|
void DrawQuickSettingsMenu();
|
||||||
void DrawDebugMenu();
|
void DrawDebugMenu();
|
||||||
|
@ -91,7 +122,10 @@ private:
|
||||||
|
|
||||||
std::string m_settings_filename;
|
std::string m_settings_filename;
|
||||||
|
|
||||||
|
KeyboardControllerActionMap m_keyboard_button_mapping;
|
||||||
|
|
||||||
std::map<int, SDL_GameController*> m_sdl_controllers;
|
std::map<int, SDL_GameController*> m_sdl_controllers;
|
||||||
|
std::array<s32, SDL_CONTROLLER_BUTTON_MAX> m_controller_button_mapping;
|
||||||
|
|
||||||
u32 m_switch_gpu_renderer_event_id = 0;
|
u32 m_switch_gpu_renderer_event_id = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue