Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/dolphin/pad.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ void PADSetAnalogMode(u32 mode);
#define PAD_KEY_MOUSE_RIGHT (-4)
#define PAD_KEY_MOUSE_X1 (-5)
#define PAD_KEY_MOUSE_X2 (-6)
#define PAD_KEY_MOUSE_AXIS_X_POS (-7)
#define PAD_KEY_MOUSE_AXIS_X_NEG (-8)
#define PAD_KEY_MOUSE_AXIS_Y_POS (-9)
#define PAD_KEY_MOUSE_AXIS_Y_NEG (-10)
typedef u16 PADButton;
typedef u32 PADExtButton;
typedef u16 PADAxis;
Expand Down
103 changes: 98 additions & 5 deletions lib/dolphin/pad/pad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
#include <sys/stat.h>
#include <ranges>

#include <SDL3/SDL_video.h>
#include "../../window.hpp"

namespace {
constexpr int32_t k_mappingsFileVersion = 3;
constexpr int32_t k_mappingsFileVersion = 4;

std::array<PADButtonMapping, PAD_BUTTON_COUNT> g_defaultButtonsStandard{{
{SDL_GAMEPAD_BUTTON_SOUTH, PAD_BUTTON_A},
Expand Down Expand Up @@ -289,8 +292,11 @@ std::array<PADButton, PAD_CHANMAX> g_suppressedButtons{};
std::array<bool, PAD_CHANMAX> g_suppressLeftTrigger{};
std::array<bool, PAD_CHANMAX> g_suppressRightTrigger{};

bool is_mouse_scancode(const s32 scancode) { return scancode < PAD_KEY_INVALID; }
bool is_mouse_button_pressed(const s32 scancode) {
bool is_mouse_scancode(s32 scancode) { return scancode < PAD_KEY_INVALID; }
bool is_mouse_axis_scancode(s32 scancode) {
return scancode <= PAD_KEY_MOUSE_AXIS_X_POS && scancode >= PAD_KEY_MOUSE_AXIS_Y_NEG;
}
bool is_mouse_button_pressed(s32 scancode) {
const int32_t buttonNum = -(scancode + 1);
if (buttonNum < 1 || buttonNum > 5) {
return false;
Expand Down Expand Up @@ -596,7 +602,35 @@ static void apply_unblock_suppression(PADStatus& status, const u32 port, const b
}
}

u32 PADRead(PADStatus* status) {
static void update_relative_mouse_mode() {
static bool sRelativeMouseMode = false;
bool shouldBeRelative = false;
if (!g_blockPAD) {
for (uint32_t i = 0; i < PAD_CHANMAX; ++i) {
if (g_keyboardBindings[i].m_mappingsSet) {
for (const auto& binding : g_keyboardBindings[i].m_axisMapping) {
if (is_mouse_axis_scancode(binding.scancode)) {
shouldBeRelative = true;
break;
}
}
}
if (shouldBeRelative)
break;
}
}

if (shouldBeRelative != sRelativeMouseMode) {
SDL_Window* window = aurora::window::get_sdl_window();
if (window) {
SDL_SetWindowRelativeMouseMode(window, shouldBeRelative);
sRelativeMouseMode = shouldBeRelative;
}
}
}

uint32_t PADRead(PADStatus* status) {
update_relative_mouse_mode();
if (!g_keyboardBindingsLoaded) {
g_keyboardBindingsLoaded = true;
load_keyboard_bindings();
Expand All @@ -607,6 +641,11 @@ u32 PADRead(PADStatus* status) {
const bool captureHeldInput = g_suppressHeldOnRead && !g_blockPAD;
g_suppressHeldOnRead = false;

float mouseDx = 0, mouseDy = 0;
if (!g_blockPAD) {
SDL_GetRelativeMouseState(&mouseDx, &mouseDy);
}

uint32_t rumbleSupport = 0;
for (uint32_t i = 0; i < PAD_CHANMAX; ++i) {
memset(&status[i], 0, sizeof(PADStatus));
Expand Down Expand Up @@ -635,6 +674,60 @@ u32 PADRead(PADStatus* status) {
bool pressed = false;
if (binding.scancode > PAD_KEY_INVALID) {
pressed = binding.scancode < numKeys && kbState[binding.scancode];
} else if (is_mouse_axis_scancode(binding.scancode)) {
float delta = 0;
switch (binding.scancode) {
case PAD_KEY_MOUSE_AXIS_X_POS:
delta = std::max(0.0f, mouseDx);
break;
case PAD_KEY_MOUSE_AXIS_X_NEG:
delta = std::max(0.0f, -mouseDx);
break;
case PAD_KEY_MOUSE_AXIS_Y_POS:
delta = std::max(0.0f, -mouseDy);
break;
case PAD_KEY_MOUSE_AXIS_Y_NEG:
delta = std::max(0.0f, mouseDy);
break;
}
if (delta > 0) {
// Apply a slight curve to the sensitivity: amount = (delta^1.1) * 5.0
// This makes slow movements precise and fast movements reach the 127 cap more naturally.
int amount = std::clamp(static_cast<int>(std::pow(delta, 1.1f) * 5.0f), 0, 127);
switch (binding.padAxis) {
case PAD_AXIS_LEFT_X_POS:
lx += amount;
break;
case PAD_AXIS_LEFT_X_NEG:
lx -= amount;
break;
case PAD_AXIS_LEFT_Y_POS:
ly += amount;
break;
case PAD_AXIS_LEFT_Y_NEG:
ly -= amount;
break;
case PAD_AXIS_RIGHT_X_POS:
rx += amount;
break;
case PAD_AXIS_RIGHT_X_NEG:
rx -= amount;
break;
case PAD_AXIS_RIGHT_Y_POS:
ry += amount;
break;
case PAD_AXIS_RIGHT_Y_NEG:
ry -= amount;
break;
case PAD_AXIS_TRIGGER_L:
tl += static_cast<int>(delta * 16.0f);
break;
case PAD_AXIS_TRIGGER_R:
tr += static_cast<int>(delta * 16.0f);
break;
}
}
continue;
} else if (is_mouse_scancode(binding.scancode)) {
pressed = is_mouse_button_pressed(binding.scancode);
}
Expand Down Expand Up @@ -1147,7 +1240,7 @@ void PADClearKeyBindings(const u32 port) {
}

constexpr uint32_t k_keyboardMagic = SBIG('KBND');
constexpr int32_t k_keyboardVersion = 3;
constexpr int32_t k_keyboardVersion = 4;

static void load_keyboard_bindings() {
const auto filePath = std::filesystem::path{aurora::g_config.configPath} / "keyboard_bindings.dat";
Expand Down
Loading