mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-11 05:03:14 +00:00
input: Don't use old input state in GameController::ReadState() (#2170)
This commit is contained in:
parent
7b8177f48e
commit
90b04e8cc0
5 changed files with 340 additions and 131 deletions
|
@ -10,6 +10,55 @@
|
|||
|
||||
namespace Input {
|
||||
|
||||
using Libraries::Pad::OrbisPadButtonDataOffset;
|
||||
|
||||
void State::OnButton(OrbisPadButtonDataOffset button, bool isPressed) {
|
||||
if (isPressed) {
|
||||
buttonsState |= button;
|
||||
} else {
|
||||
buttonsState &= ~button;
|
||||
}
|
||||
}
|
||||
|
||||
void State::OnAxis(Axis axis, int value) {
|
||||
const auto toggle = [&](const auto button) {
|
||||
if (value > 0) {
|
||||
buttonsState |= button;
|
||||
} else {
|
||||
buttonsState &= ~button;
|
||||
}
|
||||
};
|
||||
switch (axis) {
|
||||
case Axis::TriggerLeft:
|
||||
toggle(OrbisPadButtonDataOffset::L2);
|
||||
break;
|
||||
case Axis::TriggerRight:
|
||||
toggle(OrbisPadButtonDataOffset::R2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
axes[static_cast<int>(axis)] = value;
|
||||
}
|
||||
|
||||
void State::OnTouchpad(int touchIndex, bool isDown, float x, float y) {
|
||||
touchpad[touchIndex].state = isDown;
|
||||
touchpad[touchIndex].x = static_cast<u16>(x * 1920);
|
||||
touchpad[touchIndex].y = static_cast<u16>(y * 941);
|
||||
}
|
||||
|
||||
void State::OnGyro(const float gyro[3]) {
|
||||
angularVelocity.x = gyro[0];
|
||||
angularVelocity.y = gyro[1];
|
||||
angularVelocity.z = gyro[2];
|
||||
}
|
||||
|
||||
void State::OnAccel(const float accel[3]) {
|
||||
acceleration.x = accel[0];
|
||||
acceleration.y = accel[1];
|
||||
acceleration.z = accel[2];
|
||||
}
|
||||
|
||||
GameController::GameController() {
|
||||
m_states_num = 0;
|
||||
m_last_state = State();
|
||||
|
@ -20,7 +69,7 @@ void GameController::ReadState(State* state, bool* isConnected, int* connectedCo
|
|||
|
||||
*isConnected = m_connected;
|
||||
*connectedCount = m_connected_count;
|
||||
*state = GetLastState();
|
||||
*state = m_engine && m_connected ? m_engine->ReadState() : GetLastState();
|
||||
}
|
||||
|
||||
int GameController::ReadStates(State* states, int states_num, bool* isConnected,
|
||||
|
@ -75,45 +124,22 @@ void GameController::AddState(const State& state) {
|
|||
m_states_num++;
|
||||
}
|
||||
|
||||
void GameController::CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button,
|
||||
bool is_pressed) {
|
||||
void GameController::CheckButton(int id, OrbisPadButtonDataOffset button, bool is_pressed) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
auto state = GetLastState();
|
||||
|
||||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
if (is_pressed) {
|
||||
state.buttonsState |= button;
|
||||
} else {
|
||||
state.buttonsState &= ~button;
|
||||
}
|
||||
state.OnButton(button, is_pressed);
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
|
||||
void GameController::Axis(int id, Input::Axis axis, int value) {
|
||||
using Libraries::Pad::OrbisPadButtonDataOffset;
|
||||
|
||||
std::scoped_lock lock{m_mutex};
|
||||
auto state = GetLastState();
|
||||
|
||||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
int axis_id = static_cast<int>(axis);
|
||||
state.axes[axis_id] = value;
|
||||
|
||||
if (axis == Input::Axis::TriggerLeft) {
|
||||
if (value > 0) {
|
||||
state.buttonsState |= OrbisPadButtonDataOffset::L2;
|
||||
} else {
|
||||
state.buttonsState &= ~OrbisPadButtonDataOffset::L2;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis == Input::Axis::TriggerRight) {
|
||||
if (value > 0) {
|
||||
state.buttonsState |= OrbisPadButtonDataOffset::R2;
|
||||
} else {
|
||||
state.buttonsState &= ~OrbisPadButtonDataOffset::R2;
|
||||
}
|
||||
}
|
||||
state.OnAxis(axis, value);
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
|
@ -124,9 +150,7 @@ void GameController::Gyro(int id, const float gyro[3]) {
|
|||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
|
||||
// Update the angular velocity (gyro data)
|
||||
state.angularVelocity.x = gyro[0]; // X-axis
|
||||
state.angularVelocity.y = gyro[1]; // Y-axis
|
||||
state.angularVelocity.z = gyro[2]; // Z-axis
|
||||
state.OnGyro(gyro);
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
|
@ -136,9 +160,7 @@ void GameController::Acceleration(int id, const float acceleration[3]) {
|
|||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
|
||||
// Update the acceleration values
|
||||
state.acceleration.x = acceleration[0]; // X-axis
|
||||
state.acceleration.y = acceleration[1]; // Y-axis
|
||||
state.acceleration.z = acceleration[2]; // Z-axis
|
||||
state.OnAccel(acceleration);
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
|
@ -211,62 +233,48 @@ void GameController::CalculateOrientation(Libraries::Pad::OrbisFVector3& acceler
|
|||
}
|
||||
|
||||
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
|
||||
if (m_sdl_gamepad != nullptr) {
|
||||
SDL_SetGamepadLED(m_sdl_gamepad, r, g, b);
|
||||
if (!m_engine) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock _{m_mutex};
|
||||
m_engine->SetLightBarRGB(r, g, b);
|
||||
}
|
||||
|
||||
bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) {
|
||||
if (m_sdl_gamepad != nullptr) {
|
||||
return SDL_RumbleGamepad(m_sdl_gamepad, (smallMotor / 255.0f) * 0xFFFF,
|
||||
(largeMotor / 255.0f) * 0xFFFF, -1);
|
||||
void GameController::SetVibration(u8 smallMotor, u8 largeMotor) {
|
||||
if (!m_engine) {
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
std::scoped_lock _{m_mutex};
|
||||
m_engine->SetVibration(smallMotor, largeMotor);
|
||||
}
|
||||
|
||||
void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) {
|
||||
if (touchIndex < 2) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
auto state = GetLastState();
|
||||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
|
||||
state.touchpad[touchIndex].state = touchDown;
|
||||
state.touchpad[touchIndex].x = static_cast<u16>(x * 1920);
|
||||
state.touchpad[touchIndex].y = static_cast<u16>(y * 941);
|
||||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
state.OnTouchpad(touchIndex, touchDown, x, y);
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::TryOpenSDLController() {
|
||||
if (m_sdl_gamepad == nullptr || !SDL_GamepadConnected(m_sdl_gamepad)) {
|
||||
int gamepad_count;
|
||||
SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count);
|
||||
m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr;
|
||||
if (Config::getIsMotionControlsEnabled()) {
|
||||
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_GYRO, true)) {
|
||||
gyro_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_GYRO);
|
||||
LOG_INFO(Input, "Gyro initialized, poll rate: {}", gyro_poll_rate);
|
||||
} else {
|
||||
LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad");
|
||||
}
|
||||
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) {
|
||||
accel_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_ACCEL);
|
||||
LOG_INFO(Input, "Accel initialized, poll rate: {}", accel_poll_rate);
|
||||
} else {
|
||||
LOG_ERROR(Input, "Failed to initialize accel controls for gamepad");
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(gamepads);
|
||||
|
||||
SetLightBarRGB(0, 0, 255);
|
||||
void GameController::SetEngine(std::unique_ptr<Engine> engine) {
|
||||
std::scoped_lock _{m_mutex};
|
||||
m_engine = std::move(engine);
|
||||
if (m_engine) {
|
||||
m_engine->Init();
|
||||
}
|
||||
}
|
||||
|
||||
Engine* GameController::GetEngine() {
|
||||
return m_engine.get();
|
||||
}
|
||||
|
||||
u32 GameController::Poll() {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
if (m_connected) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
auto time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||
if (m_states_num == 0) {
|
||||
auto diff = (time - m_last_state.time) / 1000;
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/pad/pad.h"
|
||||
|
||||
struct SDL_Gamepad;
|
||||
|
||||
namespace Input {
|
||||
|
||||
enum class Axis {
|
||||
|
@ -28,7 +28,14 @@ struct TouchpadEntry {
|
|||
u16 y{};
|
||||
};
|
||||
|
||||
struct State {
|
||||
class State {
|
||||
public:
|
||||
void OnButton(Libraries::Pad::OrbisPadButtonDataOffset, bool);
|
||||
void OnAxis(Axis, int);
|
||||
void OnTouchpad(int touchIndex, bool isDown, float x, float y);
|
||||
void OnGyro(const float[3]);
|
||||
void OnAccel(const float[3]);
|
||||
|
||||
Libraries::Pad::OrbisPadButtonDataOffset buttonsState{};
|
||||
u64 time = 0;
|
||||
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
|
||||
|
@ -38,9 +45,19 @@ struct State {
|
|||
Libraries::Pad::OrbisFQuaternion orientation = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
};
|
||||
|
||||
class Engine {
|
||||
public:
|
||||
virtual ~Engine() = default;
|
||||
virtual void Init() = 0;
|
||||
virtual void SetLightBarRGB(u8 r, u8 g, u8 b) = 0;
|
||||
virtual void SetVibration(u8 smallMotor, u8 largeMotor) = 0;
|
||||
virtual State ReadState() = 0;
|
||||
virtual float GetAccelPollRate() const = 0;
|
||||
virtual float GetGyroPollRate() const = 0;
|
||||
};
|
||||
|
||||
inline int GetAxis(int min, int max, int value) {
|
||||
int v = (255 * (value - min)) / (max - min);
|
||||
return (v < 0 ? 0 : (v > 255 ? 255 : v));
|
||||
return std::clamp((255 * (value - min)) / (max - min), 0, 255);
|
||||
}
|
||||
|
||||
constexpr u32 MAX_STATES = 64;
|
||||
|
@ -59,13 +76,12 @@ public:
|
|||
void Gyro(int id, const float gyro[3]);
|
||||
void Acceleration(int id, const float acceleration[3]);
|
||||
void SetLightBarRGB(u8 r, u8 g, u8 b);
|
||||
bool SetVibration(u8 smallMotor, u8 largeMotor);
|
||||
void SetVibration(u8 smallMotor, u8 largeMotor);
|
||||
void SetTouchpadState(int touchIndex, bool touchDown, float x, float y);
|
||||
void TryOpenSDLController();
|
||||
void SetEngine(std::unique_ptr<Engine>);
|
||||
Engine* GetEngine();
|
||||
u32 Poll();
|
||||
|
||||
float gyro_poll_rate;
|
||||
float accel_poll_rate;
|
||||
static void CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration,
|
||||
Libraries::Pad::OrbisFVector3& angularVelocity,
|
||||
float deltaTime,
|
||||
|
@ -85,7 +101,7 @@ private:
|
|||
std::array<State, MAX_STATES> m_states;
|
||||
std::array<StateInternal, MAX_STATES> m_private;
|
||||
|
||||
SDL_Gamepad* m_sdl_gamepad = nullptr;
|
||||
std::unique_ptr<Engine> m_engine = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Input
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue