mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-04-08 18:41:30 -06:00
Moved mouse gyro to its own struct, adjusted mouse to gyro behavior to be more correct
Moved mouse gyro to its own struct, adjusted mouse to gyro behavior to be more correct
This commit is contained in:
parent
1b5cb9a4eb
commit
669cbacc29
@ -34,13 +34,6 @@
|
||||
|
||||
LOG_CHANNEL(sys_log, "SYS");
|
||||
|
||||
// Mouse-based motion sensor emulation state.
|
||||
std::atomic<bool> g_mouse_gyro_rmb{false}; // Whether right mouse button is currently held (gyro active)
|
||||
std::atomic<s32> g_mouse_gyro_dx{0}; // Accumulated mouse X delta
|
||||
std::atomic<s32> g_mouse_gyro_dy{0}; // Accumulated mouse Y delta
|
||||
std::atomic<s32> g_mouse_gyro_wheel{0}; // Accumulated mouse wheel delta
|
||||
std::atomic<bool> g_mouse_gyro_reset{false}; // One-shot reset request on right mouse button release
|
||||
|
||||
extern void pad_state_notify_state_change(usz index, u32 state);
|
||||
extern bool is_input_allowed();
|
||||
extern std::string g_input_config_override;
|
||||
@ -88,6 +81,9 @@ void pad_thread::Init()
|
||||
{
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
// Reset mouse-based gyro state
|
||||
m_mouse_gyro.clear();
|
||||
|
||||
// Cache old settings if possible
|
||||
std::array<pad_setting, CELL_PAD_MAX_PORT_NUM> pad_settings;
|
||||
for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; i++) // max 7 pads
|
||||
@ -614,38 +610,33 @@ void pad_thread::operator()()
|
||||
// The Qt frontend accumulates deltas while RMB is held.
|
||||
if (Emu.IsRunning())
|
||||
{
|
||||
const bool reset = g_mouse_gyro_reset.exchange(false);
|
||||
const bool reset = m_mouse_gyro.reset;
|
||||
|
||||
const s32 dx = g_mouse_gyro_dx.exchange(0);
|
||||
const s32 dy = g_mouse_gyro_dy.exchange(0);
|
||||
const s32 wh = g_mouse_gyro_wheel.exchange(0);
|
||||
const s32 gyro_x = m_mouse_gyro.gyro_x;
|
||||
const s32 gyro_y = m_mouse_gyro.gyro_y;
|
||||
const s32 gyro_z = m_mouse_gyro.gyro_z;
|
||||
|
||||
if (dx || dy || wh || reset)
|
||||
if (gyro_x || gyro_y || gyro_z || reset)
|
||||
{
|
||||
const auto clamp_u16_0_1023 = [](s32 v) -> u16
|
||||
{
|
||||
return static_cast<u16>(std::clamp(v, 0, 1023));
|
||||
};
|
||||
auto& pad = m_pads[0];
|
||||
|
||||
for (const auto& pad : m_pads)
|
||||
if (pad && pad->is_connected())
|
||||
{
|
||||
if (!pad || !pad->is_connected())
|
||||
continue;
|
||||
|
||||
if (reset)
|
||||
{
|
||||
// RMB released → reset motion
|
||||
pad->m_sensors[0].m_value = DEFAULT_MOTION_X;
|
||||
pad->m_sensors[1].m_value = DEFAULT_MOTION_Y;
|
||||
pad->m_sensors[2].m_value = DEFAULT_MOTION_Z;
|
||||
m_mouse_gyro.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// RMB held → accumulate motion
|
||||
// Axes have been chosen as tested in Sly 4 minigames. Top-down view motion uses X/Z axes.
|
||||
pad->m_sensors[0].m_value = clamp_u16_0_1023(static_cast<s32>(pad->m_sensors[0].m_value) + dx); // Mouse X → Motion X
|
||||
pad->m_sensors[1].m_value = clamp_u16_0_1023(static_cast<s32>(pad->m_sensors[1].m_value) + wh); // Mouse Wheel → Motion Y
|
||||
pad->m_sensors[2].m_value = clamp_u16_0_1023(static_cast<s32>(pad->m_sensors[2].m_value) + dy); // Mouse Y → Motion Z
|
||||
pad->m_sensors[0].m_value = gyro_x; // Mouse X → Motion X
|
||||
pad->m_sensors[1].m_value = gyro_y; // Mouse Wheel → Motion Y
|
||||
pad->m_sensors[2].m_value = gyro_z; // Mouse Y → Motion Z
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -985,3 +976,31 @@ void pad_thread::open_home_menu()
|
||||
(result ? input_log.error : input_log.notice)("opened home menu with result %d", s32{result});
|
||||
}
|
||||
}
|
||||
|
||||
void pad_thread::mouse_gyro_rmb_down()
|
||||
{
|
||||
m_mouse_gyro.rmb = true;
|
||||
}
|
||||
|
||||
void pad_thread::mouse_gyro_rmb_up()
|
||||
{
|
||||
m_mouse_gyro.rmb = false;
|
||||
m_mouse_gyro.reset = true;
|
||||
}
|
||||
|
||||
void pad_thread::mouse_gyro_set_xz(s32 off_x, s32 off_y)
|
||||
{
|
||||
if (!m_mouse_gyro.rmb)
|
||||
return;
|
||||
|
||||
m_mouse_gyro.gyro_x = static_cast<u16>(std::clamp(off_x, 0, DEFAULT_MOTION_X * 2 - 1));
|
||||
m_mouse_gyro.gyro_z = static_cast<u16>(std::clamp(off_y, 0, DEFAULT_MOTION_Z * 2 - 1));
|
||||
}
|
||||
|
||||
void pad_thread::mouse_gyro_set_y(s32 steps)
|
||||
{
|
||||
if (!m_mouse_gyro.rmb)
|
||||
return;
|
||||
|
||||
m_mouse_gyro.gyro_y = static_cast<u16>(std::clamp(m_mouse_gyro.gyro_y + steps, 0, DEFAULT_MOTION_Y * 2 - 1));
|
||||
}
|
||||
|
||||
@ -41,6 +41,11 @@ public:
|
||||
|
||||
static auto constexpr thread_name = "Pad Thread"sv;
|
||||
|
||||
void mouse_gyro_rmb_down();
|
||||
void mouse_gyro_rmb_up();
|
||||
void mouse_gyro_set_xz(s32 off_x, s32 off_y);
|
||||
void mouse_gyro_set_y(s32 steps);
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
void InitLddPad(u32 handle, const u32* port_status);
|
||||
@ -67,6 +72,27 @@ private:
|
||||
bool m_resume_emulation_flag = false;
|
||||
bool m_ps_button_pressed = false;
|
||||
atomic_t<bool> m_home_menu_open = false;
|
||||
|
||||
// Mouse-based motion sensor emulation state.
|
||||
struct mouse_gyro_state
|
||||
{
|
||||
bool rmb = false; // Whether right mouse button is currently held (gyro active)
|
||||
s32 gyro_x = DEFAULT_MOTION_X; // Accumulated from mouse X position relative to center
|
||||
s32 gyro_y = DEFAULT_MOTION_Y; // Accumulated from mouse wheel delta
|
||||
s32 gyro_z = DEFAULT_MOTION_Z; // Accumulated from mouse Y position relative to center
|
||||
bool reset = false; // One-shot reset request on right mouse button release
|
||||
|
||||
void clear()
|
||||
{
|
||||
rmb = false;
|
||||
gyro_x = DEFAULT_MOTION_X;
|
||||
gyro_y = DEFAULT_MOTION_Y;
|
||||
gyro_z = DEFAULT_MOTION_Z;
|
||||
reset = false;
|
||||
}
|
||||
};
|
||||
|
||||
mouse_gyro_state m_mouse_gyro;
|
||||
};
|
||||
|
||||
namespace pad
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "Emu/RSX/Overlays/overlay_message.h"
|
||||
#include "Emu/Io/interception.h"
|
||||
#include "Emu/Io/recording_config.h"
|
||||
#include "Input/pad_thread.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
@ -62,13 +63,6 @@ namespace pad
|
||||
extern atomic_t<bool> g_home_menu_requested;
|
||||
}
|
||||
|
||||
// Mouse-based motion sensor emulation state (defined in pad_thread)
|
||||
extern std::atomic<bool> g_mouse_gyro_rmb;
|
||||
extern std::atomic<s32> g_mouse_gyro_dx;
|
||||
extern std::atomic<s32> g_mouse_gyro_dy;
|
||||
extern std::atomic<s32> g_mouse_gyro_wheel;
|
||||
extern std::atomic<bool> g_mouse_gyro_reset;
|
||||
|
||||
gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon, std::shared_ptr<gui_settings> gui_settings, bool force_fullscreen)
|
||||
: QWindow()
|
||||
, m_initial_geometry(geometry)
|
||||
@ -1226,67 +1220,63 @@ bool gs_frame::event(QEvent* ev)
|
||||
|
||||
// Hardcoded mouse-based motion input.
|
||||
// Captures mouse events while the game window is focused.
|
||||
// Accumulates deltas for motion sensor emulation when RMB is held.
|
||||
// Updates motion sensor values via mouse position and mouse wheel while RMB is held.
|
||||
// Intentionally independent of chosen pad configuration.
|
||||
if (Emu.IsRunning())
|
||||
{
|
||||
switch (ev->type())
|
||||
if (auto* pad_thr = pad::get_pad_thread(true))
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
if (e->button() == Qt::RightButton)
|
||||
switch (ev->type())
|
||||
{
|
||||
// Enable mouse-driven gyro emulation while RMB is held.
|
||||
g_mouse_gyro_rmb.store(true);
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
if (e->button() == Qt::RightButton)
|
||||
{
|
||||
// Enable mouse-driven gyro emulation while RMB is held.
|
||||
pad_thr->mouse_gyro_rmb_down();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
if (e->button() == Qt::RightButton)
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
// Disable gyro emulation and request a one-shot motion reset.
|
||||
g_mouse_gyro_rmb.store(false);
|
||||
g_mouse_gyro_reset.store(true);
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
if (e->button() == Qt::RightButton)
|
||||
{
|
||||
// Disable gyro emulation and request a one-shot motion reset.
|
||||
pad_thr->mouse_gyro_rmb_up();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
// Track relative mouse movement using a persistent last cursor position.
|
||||
static QPoint last;
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
const QPoint cur = e->pos();
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
auto* e = static_cast<QMouseEvent*>(ev);
|
||||
|
||||
// Initialize reference position on first event.
|
||||
if (last.isNull())
|
||||
last = cur;
|
||||
// Track cursor offset from window center.
|
||||
const QPoint center(width() / 2, height() / 2);
|
||||
const QPoint cur = e->position().toPoint();
|
||||
|
||||
const s32 dx = cur.x() - last.x();
|
||||
const s32 dy = cur.y() - last.y();
|
||||
last = cur;
|
||||
const s32 off_x = cur.x() - center.x() + DEFAULT_MOTION_X;
|
||||
const s32 off_y = cur.y() - center.y() + DEFAULT_MOTION_Z;
|
||||
|
||||
// Accumulate deltas while gyro emulation is active.
|
||||
if (g_mouse_gyro_rmb.load())
|
||||
{
|
||||
g_mouse_gyro_dx.fetch_add(dx);
|
||||
g_mouse_gyro_dy.fetch_add(dy);
|
||||
// Determine motion from relative mouse position while gyro emulation is active.
|
||||
pad_thr->mouse_gyro_set_xz(off_x, off_y);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
// Accumulate mouse wheel steps while gyro emulation is active.
|
||||
auto* e = static_cast<QWheelEvent*>(ev);
|
||||
if (g_mouse_gyro_rmb.load())
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
auto* e = static_cast<QWheelEvent*>(ev);
|
||||
|
||||
// Track mouse wheels steps.
|
||||
const s32 steps = e->angleDelta().y() / 120;
|
||||
g_mouse_gyro_wheel.fetch_add(steps);
|
||||
|
||||
// Accumulate mouse wheel steps while gyro emulation is active.
|
||||
pad_thr->mouse_gyro_set_y(steps);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user