Moved mouse_gyro_state into its own class

Moved mouse_gyro_state into its own class
This commit is contained in:
Windsurf7 2026-01-30 15:36:41 +03:00
parent a873f46309
commit 7cfbea8a3a
7 changed files with 114 additions and 94 deletions

View File

@ -0,0 +1,63 @@
#include "mouse_gyro_state.h"
void mouse_gyro_state::clear()
{
active = false;
reset = false;
gyro_x = DEFAULT_MOTION_X;
gyro_y = DEFAULT_MOTION_Y;
gyro_z = DEFAULT_MOTION_Z;
}
void mouse_gyro_state::set_gyro_active()
{
active = true;
}
void mouse_gyro_state::set_gyro_reset()
{
active = false;
reset = true;
}
void mouse_gyro_state::set_gyro_xz(s32 off_x, s32 off_y)
{
if (!active)
return;
gyro_x = static_cast<u16>(std::clamp(off_x, 0, DEFAULT_MOTION_X * 2 - 1));
gyro_z = static_cast<u16>(std::clamp(off_y, 0, DEFAULT_MOTION_Z * 2 - 1));
}
void mouse_gyro_state::set_gyro_y(s32 steps)
{
if (!active)
return;
gyro_y = static_cast<u16>(std::clamp(gyro_y + steps, 0, DEFAULT_MOTION_Y * 2 - 1));
}
void mouse_gyro_state::gyro_run(const std::shared_ptr<Pad>& pad)
{
if (!pad || !pad->is_connected())
return;
// Inject mouse-based motion sensor values into pad sensors for gyro emulation.
// The Qt frontend maps cursor offset and wheel input to absolute motion values while RMB is held.
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;
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 = 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
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "util/types.hpp"
#include "Emu/Io/pad_types.h"
#include <algorithm>
// Mouse-based motion sensor emulation state.
class mouse_gyro_state
{
private:
bool active = false; // Whether right mouse button is currently held (gyro active)
bool reset = false; // One-shot reset request on right mouse button release
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
public:
void clear();
bool is_gyro_active() const { return active; }
bool needs_gyro_reset() const { return reset; }
s32 get_gyro_x() const { return gyro_x; }
s32 get_gyro_y() const { return gyro_y; }
s32 get_gyro_z() const { return gyro_z; }
void set_gyro_active();
void set_gyro_reset();
void set_gyro_xz(s32 off_x, s32 off_y);
void set_gyro_y(s32 steps);
void gyro_run(const std::shared_ptr<Pad>& pad);
};

View File

@ -606,46 +606,13 @@ void pad_thread::operator()()
apply_copilots();
// Inject mouse-based motion sensor values into pad sensors for gyro emulation.
// The Qt frontend maps cursor offset and wheel input to absolute motion values while RMB is held.
if (Emu.IsRunning())
{
const bool reset = m_mouse_gyro.reset;
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 (gyro_x || gyro_y || gyro_z || reset)
{
// Mouse-based gyro input is intentionally bound to Player 1 only.
auto& pad = m_pads[0];
if (pad && pad->is_connected())
{
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 = 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
}
}
}
}
if (Emu.IsRunning())
{
update_pad_states();
// Inject mouse-based motion sensor values into pad sensors for gyro emulation.
// Intentionally bound to Player 1 only.
m_mouse_gyro.gyro_run(m_pads[0]);
}
m_info.now_connect = connected_devices + num_ldd_pad;
@ -977,31 +944,3 @@ 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));
}

View File

@ -5,6 +5,7 @@
#include "Emu/Io/pad_types.h"
#include "Emu/Io/pad_config.h"
#include "Emu/Io/pad_config_types.h"
#include "Input/mouse_gyro_state.h"
#include "Utilities/mutex.h"
#include <map>
@ -41,10 +42,7 @@ 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);
mouse_gyro_state m_mouse_gyro;
protected:
void Init();
@ -72,27 +70,6 @@ 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
{
std::atomic<bool> rmb {false}; // Whether right mouse button is currently held (gyro active)
std::atomic<s32> gyro_x {DEFAULT_MOTION_X}; // Accumulated from mouse X position relative to center
std::atomic<s32> gyro_y {DEFAULT_MOTION_Y}; // Accumulated from mouse wheel delta
std::atomic<s32> gyro_z {DEFAULT_MOTION_Z}; // Accumulated from mouse Y position relative to center
std::atomic<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

View File

@ -194,6 +194,7 @@
<ClCompile Include="Input\dualsense_pad_handler.cpp" />
<ClCompile Include="Input\gui_pad_thread.cpp" />
<ClCompile Include="Input\hid_pad_handler.cpp" />
<ClCompile Include="Input\mouse_gyro_state.cpp" />
<ClCompile Include="Input\ps_move_calibration.cpp" />
<ClCompile Include="Input\ps_move_config.cpp" />
<ClCompile Include="Input\ps_move_tracker.cpp" />
@ -1079,6 +1080,7 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<ClInclude Include="Input\mouse_gyro_state.h" />
<ClInclude Include="Input\ps_move_calibration.h" />
<ClInclude Include="Input\ps_move_config.h" />
<ClInclude Include="Input\ps_move_tracker.h" />

View File

@ -1272,6 +1272,9 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_context_menu.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="Input\mouse_gyro_state.cpp">
<Filter>Io</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Input\ds4_pad_handler.h">
@ -1511,6 +1514,9 @@
<ClInclude Include="Input\sdl_camera_video_sink.h">
<Filter>Io\camera</Filter>
</ClInclude>
<ClInclude Include="Input\mouse_gyro_state.h">
<Filter>Io</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">

View File

@ -1234,7 +1234,7 @@ bool gs_frame::event(QEvent* ev)
if (e->button() == Qt::RightButton)
{
// Enable mouse-driven gyro emulation while RMB is held.
pad_thr->mouse_gyro_rmb_down();
pad_thr->m_mouse_gyro.set_gyro_active();
}
break;
}
@ -1244,7 +1244,7 @@ bool gs_frame::event(QEvent* ev)
if (e->button() == Qt::RightButton)
{
// Disable gyro emulation and request a one-shot motion reset.
pad_thr->mouse_gyro_rmb_up();
pad_thr->m_mouse_gyro.set_gyro_reset();
}
break;
}
@ -1260,7 +1260,7 @@ bool gs_frame::event(QEvent* ev)
const s32 off_y = cur.y() - center.y() + DEFAULT_MOTION_Z;
// Determine motion from relative mouse position while gyro emulation is active.
pad_thr->mouse_gyro_set_xz(off_x, off_y);
pad_thr->m_mouse_gyro.set_gyro_xz(off_x, off_y);
break;
}
@ -1272,7 +1272,7 @@ bool gs_frame::event(QEvent* ev)
const s32 steps = e->angleDelta().y() / 120;
// Accumulate mouse wheel steps while gyro emulation is active.
pad_thr->mouse_gyro_set_y(steps);
pad_thr->m_mouse_gyro.set_gyro_y(steps);
break;
}