mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-02-21 23:24:58 +01:00
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.7, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.7, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (0, 51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (1, 8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang ${{ matrix.arch }} (aarch64, clang, clangarm64, ARM64, windows-11-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang ${{ matrix.arch }} (x86_64, clang, clang64, X64, windows-2025) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run
This change adds a hardcoded mouse-based motion sensor emulation feature, inspired by how Cemu handles mouse-driven gyro input. While the game window is focused, holding the right mouse button enables gyro emulation: - Mouse X movement feeds Motion X - Mouse Y movement feeds Motion Z - Mouse Wheel feeds Motion Y The axis mapping and behavior were tested with the "Spark Runner" minigame in _Sly Cooper: Thieves in Time_ and _Bentley's Hackpack_. In accordance with this minigame, a top-down view motion control scheme relies on the X/Z axes. While the right mouse button is being held, mouse deltas are captured via the Qt native event filter and accumulated in the frontend, then consumed by the pad thread. On right mouse button release, motion values are reset to the neutral center to avoid residual drift. This input path is intentionally independent of pad configuration and works even when a keyboard-only profile is selected. This implementation thus resolves issue #13883 by allowing motion-only gameplay without requiring a physical motion-capable controller.
115 lines
2.8 KiB
C++
115 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include "util/types.hpp"
|
|
#include "util/atomic.hpp"
|
|
#include "Emu/Io/pad_types.h"
|
|
#include "Emu/Io/pad_config.h"
|
|
#include "Emu/Io/pad_config_types.h"
|
|
#include "Input/mouse_gyro_handler.h"
|
|
#include "Utilities/mutex.h"
|
|
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <string_view>
|
|
#include <string>
|
|
|
|
class PadHandlerBase;
|
|
|
|
class pad_thread
|
|
{
|
|
public:
|
|
pad_thread(void* curthread, void* curwindow, std::string_view title_id); // void * instead of QThread * and QWindow * because of include in emucore
|
|
pad_thread(const pad_thread&) = delete;
|
|
pad_thread& operator=(const pad_thread&) = delete;
|
|
~pad_thread();
|
|
|
|
void operator()();
|
|
|
|
PadInfo& GetInfo() { return m_info; }
|
|
std::array<std::shared_ptr<Pad>, CELL_PAD_MAX_PORT_NUM>& GetPads() { return m_pads; }
|
|
void SetRumble(u32 pad, u8 large_motor, u8 small_motor);
|
|
void SetIntercepted(bool intercepted);
|
|
|
|
s32 AddLddPad();
|
|
void UnregisterLddPad(u32 handle);
|
|
|
|
void open_home_menu();
|
|
|
|
std::map<pad_handler, std::shared_ptr<PadHandlerBase>>& get_handlers() { return m_handlers; }
|
|
|
|
static std::shared_ptr<PadHandlerBase> GetHandler(pad_handler type);
|
|
static void InitPadConfig(cfg_pad& cfg, pad_handler type, std::shared_ptr<PadHandlerBase>& handler);
|
|
|
|
static auto constexpr thread_name = "Pad Thread"sv;
|
|
|
|
mouse_gyro_handler& get_mouse_gyro() { return m_mouse_gyro; }
|
|
|
|
protected:
|
|
void Init();
|
|
void InitLddPad(u32 handle, const u32* port_status);
|
|
|
|
// List of all handlers
|
|
std::map<pad_handler, std::shared_ptr<PadHandlerBase>> m_handlers;
|
|
|
|
// Used for pad_handler::keyboard
|
|
void* m_curthread = nullptr;
|
|
void* m_curwindow = nullptr;
|
|
|
|
PadInfo m_info{ 0, 0, false };
|
|
std::array<std::shared_ptr<Pad>, CELL_PAD_MAX_PORT_NUM> m_pads{};
|
|
std::array<bool, CELL_PAD_MAX_PORT_NUM> m_pads_connected{};
|
|
|
|
u32 num_ldd_pad = 0;
|
|
|
|
private:
|
|
void apply_copilots();
|
|
void update_pad_states();
|
|
|
|
u32 m_mask_start_press_to_resume = 0;
|
|
u64 m_track_start_press_begin_timestamp = 0;
|
|
bool m_resume_emulation_flag = false;
|
|
bool m_ps_button_pressed = false;
|
|
atomic_t<bool> m_home_menu_open = false;
|
|
|
|
mouse_gyro_handler m_mouse_gyro;
|
|
};
|
|
|
|
namespace pad
|
|
{
|
|
extern atomic_t<pad_thread*> g_pad_thread;
|
|
extern shared_mutex g_pad_mutex;
|
|
extern std::string g_title_id;
|
|
extern atomic_t<bool> g_enabled;
|
|
extern atomic_t<bool> g_reset;
|
|
extern atomic_t<bool> g_started;
|
|
extern atomic_t<bool> g_home_menu_requested;
|
|
|
|
static inline class pad_thread* get_pad_thread(bool relaxed = false)
|
|
{
|
|
if (relaxed)
|
|
{
|
|
return g_pad_thread.observe();
|
|
}
|
|
|
|
return ensure(g_pad_thread.load());
|
|
}
|
|
|
|
static inline void set_enabled(bool enabled)
|
|
{
|
|
g_enabled = enabled;
|
|
}
|
|
|
|
static inline void reset(std::string_view title_id)
|
|
{
|
|
g_title_id = title_id;
|
|
g_reset = true;
|
|
}
|
|
|
|
static inline void SetIntercepted(bool intercepted)
|
|
{
|
|
std::lock_guard lock(g_pad_mutex);
|
|
const auto handler = get_pad_thread();
|
|
handler->SetIntercepted(intercepted);
|
|
}
|
|
}
|