config: added Allow Background Input option

This commit is contained in:
Hyper 2024-11-19 03:08:08 +00:00
parent 5c954c5427
commit 8c67886539
5 changed files with 53 additions and 46 deletions

View file

@ -21,6 +21,7 @@ public:
CONFIG_DEFINE_LOCALISED("Controls", bool, CameraYInvert, false); CONFIG_DEFINE_LOCALISED("Controls", bool, CameraYInvert, false);
CONFIG_DEFINE_LOCALISED("Controls", bool, XButtonHoming, true); CONFIG_DEFINE_LOCALISED("Controls", bool, XButtonHoming, true);
CONFIG_DEFINE_LOCALISED("Controls", bool, UnleashCancel, false); CONFIG_DEFINE_LOCALISED("Controls", bool, UnleashCancel, false);
CONFIG_DEFINE_LOCALISED("Controls", bool, BackgroundInput, false);
CONFIG_DEFINE_LOCALISED("Audio", float, MusicVolume, 1.0f); CONFIG_DEFINE_LOCALISED("Audio", float, MusicVolume, 1.0f);
CONFIG_DEFINE_LOCALISED("Audio", float, SEVolume, 1.0f); CONFIG_DEFINE_LOCALISED("Audio", float, SEVolume, 1.0f);

View file

@ -137,6 +137,16 @@ CONFIG_DEFINE_DESCRIPTION_LOCALE(LogoSkip)
{ ELanguage::English, "Show the logos during the game's boot sequence." } { ELanguage::English, "Show the logos during the game's boot sequence." }
}; };
CONFIG_DEFINE_LOCALE(BackgroundInput)
{
{ ELanguage::English, "Allow Background Input" }
};
CONFIG_DEFINE_DESCRIPTION_LOCALE(BackgroundInput)
{
{ ELanguage::English, "Set whether to accept controller input whilst the game window is unfocused." }
};
CONFIG_DEFINE_LOCALE(CameraXInvert) CONFIG_DEFINE_LOCALE(CameraXInvert)
{ {
{ ELanguage::English, "Invert Camera X" } { ELanguage::English, "Invert Camera X" }

View file

@ -1,6 +1,10 @@
#include <stdafx.h> #include <stdafx.h>
#include <SDL.h> #include <SDL.h>
#include <cfg/config.h>
#include <hid/hid_detail.h> #include <hid/hid_detail.h>
#include <ui/window.h>
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
#define VIBRATION_TIMEOUT_MS 5000 #define VIBRATION_TIMEOUT_MS 5000
class Controller class Controller
@ -13,17 +17,12 @@ public:
XAMINPUT_VIBRATION vibration{ 0, 0 }; XAMINPUT_VIBRATION vibration{ 0, 0 };
Controller() = default; Controller() = default;
explicit Controller(int index) : Controller(SDL_GameControllerOpen(index)) explicit Controller(int index) : Controller(SDL_GameControllerOpen(index)) {}
{
}
Controller(SDL_GameController* controller) : controller(controller) Controller(SDL_GameController* controller) : controller(controller)
{ {
if (!controller) if (!controller)
{
return; return;
}
joystick = SDL_GameControllerGetJoystick(controller); joystick = SDL_GameControllerGetJoystick(controller);
id = SDL_JoystickInstanceID(joystick); id = SDL_JoystickInstanceID(joystick);
@ -31,20 +30,28 @@ public:
void Close() void Close()
{ {
if (controller == nullptr) if (!controller)
{
return; return;
}
SDL_GameControllerClose(controller); SDL_GameControllerClose(controller);
controller = nullptr; controller = nullptr;
joystick = nullptr; joystick = nullptr;
id = -1; id = -1;
} }
bool CanPoll()
{
return controller && (Window::s_isFocused || Config::BackgroundInput);
}
void PollAxis() void PollAxis()
{ {
if (!CanPoll())
return;
auto& pad = state; auto& pad = state;
pad.sThumbLX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); pad.sThumbLX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
pad.sThumbLY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); pad.sThumbLY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
@ -55,14 +62,13 @@ public:
pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7; pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;
} }
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
void Poll() void Poll()
{ {
if (controller == nullptr) if (!CanPoll())
{
return; return;
}
auto& pad = state; auto& pad = state;
pad.wButtons = 0; pad.wButtons = 0;
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_UP, XAMINPUT_GAMEPAD_DPAD_UP); pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_UP, XAMINPUT_GAMEPAD_DPAD_UP);
@ -87,12 +93,11 @@ public:
void SetVibration(const XAMINPUT_VIBRATION& vibration) void SetVibration(const XAMINPUT_VIBRATION& vibration)
{ {
if (controller == nullptr) if (!CanPoll())
{
return; return;
}
this->vibration = vibration; this->vibration = vibration;
SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS); SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS);
} }
}; };
@ -102,9 +107,7 @@ std::array<Controller, 4> g_controllers;
inline Controller* EnsureController(DWORD dwUserIndex) inline Controller* EnsureController(DWORD dwUserIndex)
{ {
if (!g_controllers[dwUserIndex].controller) if (!g_controllers[dwUserIndex].controller)
{
return nullptr; return nullptr;
}
return &g_controllers[dwUserIndex]; return &g_controllers[dwUserIndex];
} }
@ -114,10 +117,8 @@ inline size_t FindFreeController()
for (size_t i = 0; i < g_controllers.size(); i++) for (size_t i = 0; i < g_controllers.size(); i++)
{ {
if (!g_controllers[i].controller) if (!g_controllers[i].controller)
{
return i; return i;
} }
}
return -1; return -1;
} }
@ -127,10 +128,8 @@ inline Controller* FindController(int which)
for (auto& controller : g_controllers) for (auto& controller : g_controllers)
{ {
if (controller.id == which) if (controller.id == which)
{
return &controller; return &controller;
} }
}
return nullptr; return nullptr;
} }
@ -142,22 +141,21 @@ int HID_OnSDLEvent(void*, SDL_Event* event)
if (event->type == SDL_CONTROLLERDEVICEADDED) if (event->type == SDL_CONTROLLERDEVICEADDED)
{ {
const auto freeIndex = FindFreeController(); const auto freeIndex = FindFreeController();
if (freeIndex != -1) if (freeIndex != -1)
{
g_controllers[freeIndex] = Controller(event->cdevice.which); g_controllers[freeIndex] = Controller(event->cdevice.which);
} }
}
if (event->type == SDL_CONTROLLERDEVICEREMOVED) if (event->type == SDL_CONTROLLERDEVICEREMOVED)
{ {
auto* controller = FindController(event->cdevice.which); auto* controller = FindController(event->cdevice.which);
if (controller) if (controller)
{
controller->Close(); controller->Close();
} }
}
else if (event->type == SDL_CONTROLLERBUTTONDOWN || event->type == SDL_CONTROLLERBUTTONUP || event->type == SDL_CONTROLLERAXISMOTION) else if (event->type == SDL_CONTROLLERBUTTONDOWN || event->type == SDL_CONTROLLERBUTTONUP || event->type == SDL_CONTROLLERAXISMOTION)
{ {
auto* controller = FindController(event->cdevice.which); auto* controller = FindController(event->cdevice.which);
if (controller) if (controller)
{ {
if (event->type == SDL_CONTROLLERAXISMOTION) if (event->type == SDL_CONTROLLERAXISMOTION)
@ -181,6 +179,7 @@ void hid::detail::Init()
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1");
SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_InitSubSystem(SDL_INIT_EVENTS);
@ -193,62 +192,58 @@ void hid::detail::Init()
uint32_t hid::detail::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState) uint32_t hid::detail::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{ {
static DWORD packet; static DWORD packet;
if (!pState) if (!pState)
{
return ERROR_BAD_ARGUMENTS; return ERROR_BAD_ARGUMENTS;
}
memset(pState, 0, sizeof(*pState)); memset(pState, 0, sizeof(*pState));
pState->dwPacketNumber = packet++; pState->dwPacketNumber = packet++;
SDL_JoystickUpdate(); SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr) if (!EnsureController(dwUserIndex))
{
return ERROR_DEVICE_NOT_CONNECTED; return ERROR_DEVICE_NOT_CONNECTED;
}
pState->Gamepad = g_controllers[dwUserIndex].state; pState->Gamepad = g_controllers[dwUserIndex].state;
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
uint32_t hid::detail::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration) uint32_t hid::detail::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
{ {
if (!pVibration) if (!pVibration)
{
return ERROR_BAD_ARGUMENTS; return ERROR_BAD_ARGUMENTS;
}
SDL_JoystickUpdate(); SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex); auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr)
{ if (!controller)
return ERROR_DEVICE_NOT_CONNECTED; return ERROR_DEVICE_NOT_CONNECTED;
}
controller->SetVibration(*pVibration); controller->SetVibration(*pVibration);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
uint32_t hid::detail::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps) uint32_t hid::detail::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
{ {
if (!pCaps) if (!pCaps)
{
return ERROR_BAD_ARGUMENTS; return ERROR_BAD_ARGUMENTS;
}
SDL_JoystickUpdate(); SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex); auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr)
{ if (!controller)
return ERROR_DEVICE_NOT_CONNECTED; return ERROR_DEVICE_NOT_CONNECTED;
}
memset(pCaps, 0, sizeof(*pCaps)); memset(pCaps, 0, sizeof(*pCaps));
pCaps->Type = XAMINPUT_DEVTYPE_GAMEPAD; pCaps->Type = XAMINPUT_DEVTYPE_GAMEPAD;
pCaps->SubType = XAMINPUT_DEVSUBTYPE_GAMEPAD; // TODO: other types? pCaps->SubType = XAMINPUT_DEVSUBTYPE_GAMEPAD; // TODO: other types?
pCaps->Flags = 0; pCaps->Flags = 0;
pCaps->Gamepad = controller->state; pCaps->Gamepad = controller->state;
pCaps->Vibration = controller->vibration; pCaps->Vibration = controller->vibration;

View file

@ -333,9 +333,6 @@ SWA_API uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_S
{ {
//printf("!!! STUB !!! XamInputGetState\n"); //printf("!!! STUB !!! XamInputGetState\n");
if (!Window::s_isFocused)
return 0;
uint32_t result = hid::GetState(userIndex, state); uint32_t result = hid::GetState(userIndex, state);
if (result == ERROR_SUCCESS) if (result == ERROR_SUCCESS)
@ -349,6 +346,9 @@ SWA_API uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_S
} }
else if (userIndex == 0) else if (userIndex == 0)
{ {
if (!Window::s_isFocused)
return ERROR_SUCCESS;
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
if (GetAsyncKeyState('W') & 0x8000) if (GetAsyncKeyState('W') & 0x8000)
state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_Y; state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_Y;

View file

@ -663,6 +663,7 @@ static void DrawConfigOptions()
DrawConfigOption(rowCount++, yOffset, &Config::CameraYInvert); DrawConfigOption(rowCount++, yOffset, &Config::CameraYInvert);
DrawConfigOption(rowCount++, yOffset, &Config::XButtonHoming); DrawConfigOption(rowCount++, yOffset, &Config::XButtonHoming);
DrawConfigOption(rowCount++, yOffset, &Config::UnleashCancel); DrawConfigOption(rowCount++, yOffset, &Config::UnleashCancel);
DrawConfigOption(rowCount++, yOffset, &Config::BackgroundInput);
break; break;
case 2: // AUDIO case 2: // AUDIO
DrawConfigOption(rowCount++, yOffset, &Config::MusicVolume); DrawConfigOption(rowCount++, yOffset, &Config::MusicVolume);