mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 23:25:41 +00:00
InputManager: Support multiple mice via raw input
Only on Windows for now.
This commit is contained in:
parent
14f69b7b78
commit
330381c939
|
@ -885,9 +885,9 @@ const Controller::ControllerInfo AnalogController::INFO = {ControllerType::Analo
|
|||
s_settings,
|
||||
Controller::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void AnalogController::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void AnalogController::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
m_force_analog_on_reset = si.GetBoolValue(section, "ForceAnalogOnReset", true);
|
||||
m_analog_dpad_in_digital_mode = si.GetBoolValue(section, "AnalogDPadInDigitalMode", true);
|
||||
m_analog_deadzone = std::clamp(si.GetFloatValue(section, "AnalogDeadzone", DEFAULT_STICK_DEADZONE), 0.0f, 1.0f);
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
void ResetTransferState() override;
|
||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
using MotorState = std::array<u8, NUM_MOTORS>;
|
||||
|
|
|
@ -413,9 +413,9 @@ const Controller::ControllerInfo AnalogJoystick::INFO = {ControllerType::AnalogJ
|
|||
s_settings,
|
||||
Controller::VibrationCapabilities::NoVibration};
|
||||
|
||||
void AnalogJoystick::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void AnalogJoystick::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
m_analog_deadzone = std::clamp(si.GetFloatValue(section, "AnalogDeadzone", DEFAULT_STICK_DEADZONE), 0.0f, 1.0f);
|
||||
m_analog_sensitivity =
|
||||
std::clamp(si.GetFloatValue(section, "AnalogSensitivity", DEFAULT_STICK_SENSITIVITY), 0.01f, 3.0f);
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
void ResetTransferState() override;
|
||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
enum class TransferState : u8
|
||||
|
|
|
@ -91,7 +91,7 @@ u32 Controller::GetInputOverlayIconColor() const
|
|||
return 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
void Controller::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void Controller::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
virtual u32 GetInputOverlayIconColor() const;
|
||||
|
||||
/// Loads/refreshes any per-controller settings.
|
||||
virtual void LoadSettings(SettingsInterface& si, const char* section);
|
||||
virtual void LoadSettings(SettingsInterface& si, const char* section, bool initial);
|
||||
|
||||
/// Creates a new controller of the specified type.
|
||||
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
|
||||
|
|
|
@ -187,9 +187,9 @@ const Controller::ControllerInfo DigitalController::INFO = {ControllerType::Digi
|
|||
s_settings,
|
||||
Controller::VibrationCapabilities::NoVibration};
|
||||
|
||||
void DigitalController::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void DigitalController::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
m_popn_controller_mode = si.GetBoolValue(section, "ForcePopnControllerMode", false);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
void ResetTransferState() override;
|
||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
enum class TransferState : u8
|
||||
|
|
|
@ -207,8 +207,8 @@ bool GunCon::Transfer(const u8 data_in, u8* data_out)
|
|||
void GunCon::UpdatePosition()
|
||||
{
|
||||
float display_x, display_y;
|
||||
const auto& [window_x, window_y] =
|
||||
(m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() : InputManager::GetPointerAbsolutePosition(0);
|
||||
const auto& [window_x, window_y] = (m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() :
|
||||
InputManager::GetPointerAbsolutePosition(m_cursor_index);
|
||||
g_gpu->ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y);
|
||||
|
||||
// are we within the active display area?
|
||||
|
@ -245,7 +245,7 @@ bool GunCon::CanUseSoftwareCursor() const
|
|||
|
||||
u32 GunCon::GetSoftwarePointerIndex() const
|
||||
{
|
||||
return m_has_relative_binds ? (InputManager::MAX_POINTER_DEVICES + m_index) : 0;
|
||||
return m_has_relative_binds ? (InputManager::MAX_POINTER_DEVICES + m_index) : m_cursor_index;
|
||||
}
|
||||
|
||||
void GunCon::UpdateSoftwarePointerPosition()
|
||||
|
@ -273,6 +273,7 @@ static const Controller::ControllerBindingInfo s_binding_info[] = {
|
|||
}
|
||||
|
||||
// clang-format off
|
||||
{"Pointer", TRANSLATE_NOOP("GunCon", "Pointer/Aiming"), ICON_PF_MOUSE, static_cast<u32>(GunCon::Binding::ButtonCount), InputBindingInfo::Type::AbsolutePointer, GenericInputBinding::Unknown},
|
||||
BUTTON("Trigger", TRANSLATE_NOOP("GunCon", "Trigger"), ICON_PF_CROSS, GunCon::Binding::Trigger, GenericInputBinding::R2),
|
||||
BUTTON("ShootOffscreen", TRANSLATE_NOOP("GunCon", "Shoot Offscreen"), nullptr, GunCon::Binding::ShootOffscreen, GenericInputBinding::L2),
|
||||
BUTTON("A", TRANSLATE_NOOP("GunCon", "A"), ICON_PF_BUTTON_A, GunCon::Binding::A, GenericInputBinding::Cross),
|
||||
|
@ -306,9 +307,9 @@ const Controller::ControllerInfo GunCon::INFO = {
|
|||
ControllerType::GunCon, "GunCon", TRANSLATE_NOOP("ControllerType", "GunCon"), nullptr,
|
||||
s_binding_info, s_settings, Controller::VibrationCapabilities::NoVibration};
|
||||
|
||||
void GunCon::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void GunCon::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
|
||||
m_x_scale = si.GetFloatValue(section, "XScale", 1.0f);
|
||||
|
||||
|
@ -334,13 +335,15 @@ void GunCon::LoadSettings(SettingsInterface& si, const char* section)
|
|||
|
||||
m_has_relative_binds = (si.ContainsValue(section, "RelativeLeft") || si.ContainsValue(section, "RelativeRight") ||
|
||||
si.ContainsValue(section, "RelativeUp") || si.ContainsValue(section, "RelativeDown"));
|
||||
m_cursor_index =
|
||||
static_cast<u8>(InputManager::GetIndexFromPointerBinding(si.GetStringValue(section, "Pointer")).value_or(0));
|
||||
|
||||
const s32 new_pointer_index = GetSoftwarePointerIndex();
|
||||
|
||||
if (prev_pointer_index != new_pointer_index || m_cursor_path != cursor_path || m_cursor_scale != cursor_scale ||
|
||||
m_cursor_color != cursor_color)
|
||||
{
|
||||
if (prev_pointer_index != new_pointer_index &&
|
||||
if (!initial && prev_pointer_index != new_pointer_index &&
|
||||
static_cast<u32>(prev_pointer_index) < InputManager::MAX_SOFTWARE_CURSORS)
|
||||
{
|
||||
ImGuiManager::ClearSoftwareCursor(prev_pointer_index);
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
float GetBindState(u32 index) const override;
|
||||
void SetBindState(u32 index, float value) override;
|
||||
|
@ -80,6 +80,7 @@ private:
|
|||
u16 m_position_y = 0;
|
||||
bool m_shoot_offscreen = false;
|
||||
bool m_has_relative_binds = false;
|
||||
u8 m_cursor_index = 0;
|
||||
|
||||
TransferState m_transfer_state = TransferState::Idle;
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "util/gpu_device.h"
|
||||
#include "util/imgui_manager.h"
|
||||
#include "util/input_manager.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
|
@ -308,6 +309,8 @@ bool Host::CreateGPUDevice(RenderAPI api, Error* error)
|
|||
return false;
|
||||
}
|
||||
|
||||
InputManager::SetDisplayWindowSize(static_cast<float>(g_gpu_device->GetWindowWidth()),
|
||||
static_cast<float>(g_gpu_device->GetWindowHeight()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -322,7 +325,10 @@ void Host::UpdateDisplayWindow()
|
|||
return;
|
||||
}
|
||||
|
||||
ImGuiManager::WindowResized();
|
||||
const float f_width = static_cast<float>(g_gpu_device->GetWindowWidth());
|
||||
const float f_height = static_cast<float>(g_gpu_device->GetWindowHeight());
|
||||
ImGuiManager::WindowResized(f_width, f_height);
|
||||
InputManager::SetDisplayWindowSize(f_width, f_height);
|
||||
|
||||
if (System::IsValid())
|
||||
{
|
||||
|
@ -343,7 +349,11 @@ void Host::ResizeDisplayWindow(s32 width, s32 height, float scale)
|
|||
DEV_LOG("Display window resized to {}x{}", width, height);
|
||||
|
||||
g_gpu_device->ResizeWindow(width, height, scale);
|
||||
ImGuiManager::WindowResized();
|
||||
|
||||
const float f_width = static_cast<float>(g_gpu_device->GetWindowWidth());
|
||||
const float f_height = static_cast<float>(g_gpu_device->GetWindowHeight());
|
||||
ImGuiManager::WindowResized(f_width, f_height);
|
||||
InputManager::SetDisplayWindowSize(f_width, f_height);
|
||||
|
||||
// If we're paused, re-present the current frame at the new window size.
|
||||
if (System::IsValid())
|
||||
|
|
|
@ -16,6 +16,7 @@ struct InputBindingInfo
|
|||
HalfAxis,
|
||||
Motor,
|
||||
Pointer, // Receive relative mouse movement events, bind_index is offset by the axis.
|
||||
AbsolutePointer, // Allows selection of specific pointers, but defaults to the first.
|
||||
Macro,
|
||||
};
|
||||
|
||||
|
@ -68,4 +69,3 @@ enum class GenericInputBinding : u8
|
|||
|
||||
Count,
|
||||
};
|
||||
|
||||
|
|
|
@ -213,8 +213,8 @@ void Justifier::UpdatePosition()
|
|||
}
|
||||
|
||||
float display_x, display_y;
|
||||
const auto [window_x, window_y] =
|
||||
(m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() : InputManager::GetPointerAbsolutePosition(0);
|
||||
const auto [window_x, window_y] = (m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() :
|
||||
InputManager::GetPointerAbsolutePosition(m_cursor_index);
|
||||
g_gpu->ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y);
|
||||
|
||||
// are we within the active display area?
|
||||
|
@ -308,7 +308,7 @@ bool Justifier::CanUseSoftwareCursor() const
|
|||
|
||||
u32 Justifier::GetSoftwarePointerIndex() const
|
||||
{
|
||||
return m_has_relative_binds ? (InputManager::MAX_POINTER_DEVICES + m_index) : 0;
|
||||
return m_has_relative_binds ? (InputManager::MAX_POINTER_DEVICES + m_index) : m_cursor_index;
|
||||
}
|
||||
|
||||
void Justifier::UpdateSoftwarePointerPosition()
|
||||
|
@ -336,6 +336,7 @@ static const Controller::ControllerBindingInfo s_binding_info[] = {
|
|||
}
|
||||
|
||||
// clang-format off
|
||||
{"Pointer", TRANSLATE_NOOP("Justifier", "Pointer/Aiming"), ICON_PF_MOUSE, static_cast<u32>(Justifier::Binding::ButtonCount), InputBindingInfo::Type::AbsolutePointer, GenericInputBinding::Unknown},
|
||||
BUTTON("Trigger", TRANSLATE_NOOP("Justifier", "Trigger"), ICON_PF_CROSS, Justifier::Binding::Trigger, GenericInputBinding::R2),
|
||||
BUTTON("ShootOffscreen", TRANSLATE_NOOP("Justifier", "Shoot Offscreen"), nullptr, Justifier::Binding::ShootOffscreen, GenericInputBinding::L2),
|
||||
BUTTON("Start", TRANSLATE_NOOP("Justifier", "Start"), ICON_PF_START, Justifier::Binding::Start, GenericInputBinding::Cross),
|
||||
|
@ -395,9 +396,9 @@ const Controller::ControllerInfo Justifier::INFO = {ControllerType::Justifier,
|
|||
s_settings,
|
||||
Controller::VibrationCapabilities::NoVibration};
|
||||
|
||||
void Justifier::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void Justifier::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
|
||||
m_x_scale = si.GetFloatValue(section, "XScale", 1.0f);
|
||||
|
||||
|
@ -423,13 +424,15 @@ void Justifier::LoadSettings(SettingsInterface& si, const char* section)
|
|||
|
||||
m_has_relative_binds = (si.ContainsValue(section, "RelativeLeft") || si.ContainsValue(section, "RelativeRight") ||
|
||||
si.ContainsValue(section, "RelativeUp") || si.ContainsValue(section, "RelativeDown"));
|
||||
m_cursor_index =
|
||||
static_cast<u8>(InputManager::GetIndexFromPointerBinding(si.GetStringValue(section, "Pointer")).value_or(0));
|
||||
|
||||
const s32 new_pointer_index = GetSoftwarePointerIndex();
|
||||
|
||||
if (prev_pointer_index != new_pointer_index || m_cursor_path != cursor_path || m_cursor_scale != cursor_scale ||
|
||||
m_cursor_color != cursor_color)
|
||||
{
|
||||
if (prev_pointer_index != new_pointer_index &&
|
||||
if (!initial && prev_pointer_index != new_pointer_index &&
|
||||
static_cast<u32>(prev_pointer_index) < InputManager::MAX_SOFTWARE_CURSORS)
|
||||
{
|
||||
ImGuiManager::ClearSoftwareCursor(prev_pointer_index);
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
float GetBindState(u32 index) const override;
|
||||
void SetBindState(u32 index, float value) override;
|
||||
|
@ -100,6 +100,7 @@ private:
|
|||
TimingEvent m_irq_event;
|
||||
|
||||
bool m_has_relative_binds = false;
|
||||
u8 m_cursor_index = 0;
|
||||
float m_relative_pos[4] = {};
|
||||
|
||||
std::string m_cursor_path;
|
||||
|
|
|
@ -345,9 +345,9 @@ const Controller::ControllerInfo NeGcon::INFO = {
|
|||
ControllerType::NeGcon, "NeGcon", TRANSLATE_NOOP("ControllerType", "NeGcon"), ICON_PF_GAMEPAD,
|
||||
s_binding_info, s_settings, Controller::VibrationCapabilities::NoVibration};
|
||||
|
||||
void NeGcon::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void NeGcon::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
m_steering_modifier = {
|
||||
.deadzone = si.GetFloatValue(section, "SteeringDeadzone", DEFAULT_STEERING_MODIFIER.deadzone),
|
||||
.saturation = si.GetFloatValue(section, "SteeringSaturation", DEFAULT_STEERING_MODIFIER.saturation),
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
u32 GetButtonStateBits() const override;
|
||||
std::optional<u32> GetAnalogInputBytes() const override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
enum class TransferState : u8
|
||||
|
|
|
@ -766,9 +766,9 @@ const Controller::ControllerInfo NeGconRumble::INFO = {ControllerType::NeGconRum
|
|||
s_settings,
|
||||
Controller::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void NeGconRumble::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void NeGconRumble::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
m_steering_deadzone = si.GetFloatValue(section, "SteeringDeadzone", 0.10f);
|
||||
m_steering_sensitivity = si.GetFloatValue(section, "SteeringSensitivity", 1.00f);
|
||||
m_rumble_bias = static_cast<u8>(std::min<u32>(si.GetIntValue(section, "VibrationBias", 8), 255));
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
u32 GetButtonStateBits() const override;
|
||||
std::optional<u32> GetAnalogInputBytes() const override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
using MotorState = std::array<u8, NUM_MOTORS>;
|
||||
|
|
|
@ -181,9 +181,9 @@ bool PlayStationMouse::Transfer(const u8 data_in, u8* data_out)
|
|||
}
|
||||
}
|
||||
|
||||
void PlayStationMouse::LoadSettings(SettingsInterface& si, const char* section)
|
||||
void PlayStationMouse::LoadSettings(SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section);
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
|
||||
m_sensitivity_x = si.GetFloatValue(section, "SensitivityX", 1.0f);
|
||||
m_sensitivity_y = si.GetFloatValue(section, "SensitivityY", 1.0f);
|
||||
|
@ -219,7 +219,7 @@ static const SettingInfo s_settings[] = {
|
|||
|
||||
const Controller::ControllerInfo PlayStationMouse::INFO = {ControllerType::PlayStationMouse,
|
||||
"PlayStationMouse",
|
||||
TRANSLATE_NOOP("ControllerType", "PlayStation Mouse"),
|
||||
TRANSLATE_NOOP("ControllerType", "Mouse"),
|
||||
ICON_PF_MOUSE,
|
||||
s_binding_info,
|
||||
s_settings,
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
void ResetTransferState() override;
|
||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||
|
||||
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||
void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
enum class TransferState : u8
|
||||
|
|
|
@ -176,7 +176,6 @@ static void UpdateRunningGame(const std::string_view path, CDImage* image, bool
|
|||
static bool CheckForSBIFile(CDImage* image, Error* error);
|
||||
|
||||
static void UpdateControllers();
|
||||
static void UpdateControllerSettings();
|
||||
static void ResetControllers();
|
||||
static void UpdatePerGameMemoryCards();
|
||||
static std::unique_ptr<MemoryCard> GetMemoryCardForSlot(u32 slot, MemoryCardType type);
|
||||
|
@ -1459,6 +1458,7 @@ void System::PauseSystem(bool paused)
|
|||
FullscreenUI::OnSystemPaused();
|
||||
|
||||
InputManager::PauseVibration();
|
||||
InputManager::UpdateHostMouseMode();
|
||||
|
||||
Achievements::OnSystemPaused(true);
|
||||
|
||||
|
@ -1478,6 +1478,8 @@ void System::PauseSystem(bool paused)
|
|||
{
|
||||
FullscreenUI::OnSystemResumed();
|
||||
|
||||
InputManager::UpdateHostMouseMode();
|
||||
|
||||
Achievements::OnSystemPaused(false);
|
||||
|
||||
if (g_settings.inhibit_screensaver)
|
||||
|
@ -1732,6 +1734,8 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
|||
|
||||
FullscreenUI::OnSystemStarted();
|
||||
|
||||
InputManager::UpdateHostMouseMode();
|
||||
|
||||
if (g_settings.inhibit_screensaver)
|
||||
PlatformMisc::SuspendScreensaver();
|
||||
|
||||
|
@ -1891,6 +1895,7 @@ void System::DestroySystem()
|
|||
FullscreenUI::OnSystemDestroyed();
|
||||
|
||||
InputManager::PauseVibration();
|
||||
InputManager::UpdateHostMouseMode();
|
||||
|
||||
if (g_settings.inhibit_screensaver)
|
||||
PlatformMisc::ResumeScreensaver();
|
||||
|
@ -3548,7 +3553,7 @@ void System::UpdateControllers()
|
|||
std::unique_ptr<Controller> controller = Controller::Create(type, i);
|
||||
if (controller)
|
||||
{
|
||||
controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str());
|
||||
controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str(), true);
|
||||
Pad::SetController(i, std::move(controller));
|
||||
}
|
||||
}
|
||||
|
@ -3563,7 +3568,7 @@ void System::UpdateControllerSettings()
|
|||
{
|
||||
Controller* controller = Pad::GetController(i);
|
||||
if (controller)
|
||||
controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str());
|
||||
controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,9 @@ void ReloadInputSources();
|
|||
/// Reloads input bindings.
|
||||
void ReloadInputBindings();
|
||||
|
||||
/// Reloads only controller settings.
|
||||
void UpdateControllerSettings();
|
||||
|
||||
bool BootSystem(SystemBootParameters parameters, Error* error);
|
||||
void PauseSystem(bool paused);
|
||||
void ResetSystem();
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1010</width>
|
||||
<height>418</height>
|
||||
<width>1124</width>
|
||||
<height>485</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -22,210 +22,55 @@
|
|||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Trigger</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Fire Offscreen</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="ShootOffscreen">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_18">
|
||||
<property name="title">
|
||||
<string>Fire</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Trigger">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
<string>Pointer Setup</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
<string><html><head/><body><p>By default, lightguns will use the mouse pointer. To use the mouse, you <span style=" font-weight:700;">do not</span> need to configure any bindings apart from the trigger and buttons. Aiming only needs to be set when you want to use multiple mice.</p><p>If you want to use a controller, or lightgun which simulates a controller instead of a mouse, then you should bind it to Relative Aiming. Otherwise, Relative Aiming should be <span style=" font-weight:700;">left unbound</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Side Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>B</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="B">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_19">
|
||||
<property name="title">
|
||||
<string>A</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="A">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_20">
|
||||
<property name="title">
|
||||
<string extracomment="Try to use Sony's official terminology for this. A good place to start would be in the console or the DualShock 2's manual. If this element was officially translated to your language by Sony in later DualShocks, you may use that term.">Relative Aiming</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<widget class="QGroupBox" name="groupBox_21">
|
||||
<property name="title">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -260,52 +105,12 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RelativeLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_13">
|
||||
<widget class="QGroupBox" name="groupBox_23">
|
||||
<property name="title">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_14">
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -340,12 +145,52 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_22">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RelativeLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<widget class="QGroupBox" name="groupBox_24">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -383,34 +228,23 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -418,13 +252,13 @@
|
|||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>35</width>
|
||||
<height>263</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
|
@ -442,52 +276,302 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources/resources.qrc">:/controllers/guncon.svg</pixmap>
|
||||
<pixmap resource="resources/duckstation-qt.qrc">:/controllers/guncon.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>36</width>
|
||||
<height>263</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Pointer Setup</string>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Aiming</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Pointer">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><p>By default, lightguns will use the mouse pointer. To use the mouse, you <strong>do not</strong> need to configure any bindings apart from the trigger and buttons.</p>
|
||||
|
||||
<p>If you want to use a controller, or lightgun which simulates a controller instead of a mouse, then you should bind it to Relative Aiming. Otherwise, Relative Aiming should be <strong>left unbound</strong>.</p></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>Trigger</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Fire Offscreen</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_25">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="ShootOffscreen">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_25">
|
||||
<property name="title">
|
||||
<string>Fire</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_26">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Trigger">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_26">
|
||||
<property name="title">
|
||||
<string>Side Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_27">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_27">
|
||||
<property name="title">
|
||||
<string>B</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_28">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="B">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_28">
|
||||
<property name="title">
|
||||
<string>A</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_29">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="A">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
@ -498,7 +582,8 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1010</width>
|
||||
<height>418</height>
|
||||
<width>1124</width>
|
||||
<height>485</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -22,210 +22,55 @@
|
|||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Trigger</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Fire Offscreen</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="ShootOffscreen">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_18">
|
||||
<property name="title">
|
||||
<string>Fire</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Trigger">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
<string>Pointer Setup</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
<string><html><head/><body><p>By default, lightguns will use the mouse pointer. To use the mouse, you <span style=" font-weight:700;">do not</span> need to configure any bindings apart from the trigger and buttons. Aiming only needs to be set when you want to use multiple mice.</p><p>If you want to use a controller, or lightgun which simulates a controller instead of a mouse, then you should bind it to Relative Aiming. Otherwise, Relative Aiming should be <span style=" font-weight:700;">left unbound</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Side Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Back">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_19">
|
||||
<property name="title">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_20">
|
||||
<property name="title">
|
||||
<string extracomment="Try to use Sony's official terminology for this. A good place to start would be in the console or the DualShock 2's manual. If this element was officially translated to your language by Sony in later DualShocks, you may use that term.">Relative Aiming</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<widget class="QGroupBox" name="groupBox_21">
|
||||
<property name="title">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -260,52 +105,12 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RelativeLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_13">
|
||||
<widget class="QGroupBox" name="groupBox_23">
|
||||
<property name="title">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_14">
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -340,12 +145,52 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_22">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RelativeLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<widget class="QGroupBox" name="groupBox_24">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -383,34 +228,23 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -418,13 +252,13 @@
|
|||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>35</width>
|
||||
<height>263</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
|
@ -442,52 +276,302 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources/resources.qrc">:/controllers/justifier.svg</pixmap>
|
||||
<pixmap resource="resources/duckstation-qt.qrc">:/controllers/justifier.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>36</width>
|
||||
<height>263</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Pointer Setup</string>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Aiming</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Pointer">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><p>By default, lightguns will use the mouse pointer. To use the mouse, you <strong>do not</strong> need to configure any bindings apart from the trigger and buttons.</p>
|
||||
|
||||
<p>If you want to use a controller, or lightgun which simulates a controller instead of a mouse, then you should bind it to Relative Aiming. Otherwise, Relative Aiming should be <strong>left unbound</strong>.</p></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>Trigger</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Fire Offscreen</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_25">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="ShootOffscreen">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_25">
|
||||
<property name="title">
|
||||
<string>Fire</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_26">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Trigger">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_26">
|
||||
<property name="title">
|
||||
<string>Side Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_27">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_27">
|
||||
<property name="title">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_28">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Back">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_28">
|
||||
<property name="title">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_29">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
@ -498,7 +582,8 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>534</height>
|
||||
<height>567</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -29,7 +29,124 @@
|
|||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="5">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources/duckstation-qt.qrc">:/controllers/mouse.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="6">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Pointer</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Pointer">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
|
@ -47,46 +164,6 @@
|
|||
<string>Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Right">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
|
@ -108,8 +185,48 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Left">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Right">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -130,55 +247,10 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources/resources.qrc">:/controllers/mouse.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
@ -189,6 +261,8 @@
|
|||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -198,7 +272,8 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
<include location="resources/duckstation-qt.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -478,7 +478,8 @@ void ControllerBindingWidget::bindBindingWidgets(QWidget* parent)
|
|||
for (const Controller::ControllerBindingInfo& bi : m_controller_info->bindings)
|
||||
{
|
||||
if (bi.type == InputBindingInfo::Type::Axis || bi.type == InputBindingInfo::Type::HalfAxis ||
|
||||
bi.type == InputBindingInfo::Type::Button || bi.type == InputBindingInfo::Type::Pointer)
|
||||
bi.type == InputBindingInfo::Type::Button || bi.type == InputBindingInfo::Type::Pointer ||
|
||||
bi.type == InputBindingInfo::Type::AbsolutePointer)
|
||||
{
|
||||
InputBindingWidget* widget = parent->findChild<InputBindingWidget*>(QString::fromUtf8(bi.name));
|
||||
if (!widget)
|
||||
|
|
|
@ -100,11 +100,9 @@ void DisplayWidget::updateRelativeMode(bool enabled)
|
|||
|
||||
if (enabled)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_relative_mouse_enabled = !clip_cursor;
|
||||
m_clip_mouse_enabled = clip_cursor;
|
||||
#else
|
||||
m_relative_mouse_enabled = true;
|
||||
#ifdef _WIN32
|
||||
m_clip_mouse_enabled = clip_cursor;
|
||||
#endif
|
||||
m_relative_mouse_start_pos = QCursor::pos();
|
||||
updateCenterPos();
|
||||
|
@ -263,12 +261,10 @@ bool DisplayWidget::event(QEvent* event)
|
|||
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
const QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
||||
|
||||
if (!m_relative_mouse_enabled)
|
||||
{
|
||||
const qreal dpr = QtUtils::GetDevicePixelRatioForWidget(this);
|
||||
const QPoint mouse_pos = mouse_event->pos();
|
||||
const QPoint mouse_pos = static_cast<QMouseEvent*>(event)->pos();
|
||||
|
||||
const float scaled_x = static_cast<float>(static_cast<qreal>(mouse_pos.x()) * dpr);
|
||||
const float scaled_y = static_cast<float>(static_cast<qreal>(mouse_pos.y()) * dpr);
|
||||
|
@ -298,11 +294,14 @@ bool DisplayWidget::event(QEvent* event)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!InputManager::IsUsingRawInput())
|
||||
{
|
||||
if (dx != 0.0f)
|
||||
InputManager::UpdatePointerRelativeDelta(0, InputPointerAxis::X, dx);
|
||||
if (dy != 0.0f)
|
||||
InputManager::UpdatePointerRelativeDelta(0, InputPointerAxis::Y, dy);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -310,9 +309,12 @@ bool DisplayWidget::event(QEvent* event)
|
|||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if (!m_relative_mouse_enabled || !InputManager::IsUsingRawInput())
|
||||
{
|
||||
const u32 button_index = CountTrailingZeros(static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()));
|
||||
emit windowMouseButtonEvent(static_cast<int>(button_index), event->type() != QEvent::MouseButtonRelease);
|
||||
}
|
||||
|
||||
// don't toggle fullscreen when we're bound.. that wouldn't end well.
|
||||
if (event->type() == QEvent::MouseButtonDblClick &&
|
||||
|
|
|
@ -269,6 +269,8 @@ void InputBindingDialog::saveListToSettings()
|
|||
else
|
||||
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
if (m_bind_type == InputBindingInfo::Type::Pointer || m_bind_type == InputBindingInfo::Type::AbsolutePointer)
|
||||
g_emu_thread->updateControllerSettings();
|
||||
g_emu_thread->reloadInputBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,9 @@ InputBindingWidget::~InputBindingWidget()
|
|||
|
||||
bool InputBindingWidget::isMouseMappingEnabled(SettingsInterface* sif)
|
||||
{
|
||||
return sif ? sif->GetBoolValue("UI", "EnableMouseMapping", false) :
|
||||
Host::GetBaseBoolSettingValue("UI", "EnableMouseMapping", false);
|
||||
return (sif ? sif->GetBoolValue("UI", "EnableMouseMapping", false) :
|
||||
Host::GetBaseBoolSettingValue("UI", "EnableMouseMapping", false)) &&
|
||||
!InputManager::IsUsingRawInput();
|
||||
}
|
||||
|
||||
void InputBindingWidget::initialize(SettingsInterface* sif, InputBindingInfo::Type bind_type, std::string section_name,
|
||||
|
@ -100,7 +101,7 @@ bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
|||
const QEvent::Type event_type = event->type();
|
||||
|
||||
// if the key is being released, set the input
|
||||
if (event_type == QEvent::KeyRelease || event_type == QEvent::MouseButtonRelease)
|
||||
if (event_type == QEvent::KeyRelease || (event_type == QEvent::MouseButtonRelease && m_mouse_mapping_enabled))
|
||||
{
|
||||
setNewBinding();
|
||||
stopListeningForInput();
|
||||
|
@ -112,7 +113,8 @@ bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
|||
m_new_bindings.push_back(InputManager::MakeHostKeyboardKey(QtUtils::KeyEventToCode(key_event)));
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
|
||||
else if ((event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick) &&
|
||||
m_mouse_mapping_enabled)
|
||||
{
|
||||
// double clicks get triggered if we click bind, then click again quickly.
|
||||
const u32 button_index = CountTrailingZeros(static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()));
|
||||
|
@ -225,6 +227,8 @@ void InputBindingWidget::setNewBinding()
|
|||
{
|
||||
Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
if (m_bind_type == InputBindingInfo::Type::Pointer || m_bind_type == InputBindingInfo::Type::AbsolutePointer)
|
||||
g_emu_thread->updateControllerSettings();
|
||||
g_emu_thread->reloadInputBindings();
|
||||
}
|
||||
}
|
||||
|
@ -246,6 +250,8 @@ void InputBindingWidget::clearBinding()
|
|||
{
|
||||
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
if (m_bind_type == InputBindingInfo::Type::Pointer || m_bind_type == InputBindingInfo::Type::AbsolutePointer)
|
||||
g_emu_thread->updateControllerSettings();
|
||||
g_emu_thread->reloadInputBindings();
|
||||
}
|
||||
reloadBinding();
|
||||
|
|
|
@ -753,6 +753,20 @@ void EmuThread::updateEmuFolders()
|
|||
EmuFolders::Update();
|
||||
}
|
||||
|
||||
void EmuThread::updateControllerSettings()
|
||||
{
|
||||
if (!isOnThread())
|
||||
{
|
||||
QMetaObject::invokeMethod(this, &EmuThread::updateControllerSettings, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!System::IsValid())
|
||||
return;
|
||||
|
||||
System::UpdateControllerSettings();
|
||||
}
|
||||
|
||||
void EmuThread::startFullscreenUI()
|
||||
{
|
||||
if (!isOnThread())
|
||||
|
|
|
@ -159,6 +159,7 @@ public Q_SLOTS:
|
|||
void applySettings(bool display_osd_messages = false);
|
||||
void reloadGameSettings(bool display_osd_messages = false);
|
||||
void updateEmuFolders();
|
||||
void updateControllerSettings();
|
||||
void reloadInputSources();
|
||||
void reloadInputBindings();
|
||||
void reloadInputDevices();
|
||||
|
|
|
@ -233,14 +233,11 @@ float ImGuiManager::GetWindowHeight()
|
|||
return s_window_height;
|
||||
}
|
||||
|
||||
void ImGuiManager::WindowResized()
|
||||
void ImGuiManager::WindowResized(float width, float height)
|
||||
{
|
||||
const u32 new_width = g_gpu_device ? g_gpu_device->GetWindowWidth() : 0;
|
||||
const u32 new_height = g_gpu_device ? g_gpu_device->GetWindowHeight() : 0;
|
||||
|
||||
s_window_width = static_cast<float>(new_width);
|
||||
s_window_height = static_cast<float>(new_height);
|
||||
ImGui::GetIO().DisplaySize = ImVec2(s_window_width, s_window_height);
|
||||
s_window_width = width;
|
||||
s_window_height = height;
|
||||
ImGui::GetIO().DisplaySize = ImVec2(width, height);
|
||||
|
||||
// Scale might have changed as a result of window resize.
|
||||
RequestScaleUpdate();
|
||||
|
@ -1053,7 +1050,7 @@ void ImGuiManager::DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<
|
|||
void ImGuiManager::RenderSoftwareCursors()
|
||||
{
|
||||
// This one's okay to race, worst that happens is we render the wrong number of cursors for a frame.
|
||||
const u32 pointer_count = InputManager::MAX_POINTER_DEVICES;
|
||||
const u32 pointer_count = InputManager::GetPointerCount();
|
||||
for (u32 i = 0; i < pointer_count; i++)
|
||||
DrawSoftwareCursor(s_software_cursors[i], InputManager::GetPointerAbsolutePosition(i));
|
||||
|
||||
|
@ -1076,8 +1073,8 @@ void ImGuiManager::SetSoftwareCursor(u32 index, std::string image_path, float im
|
|||
UpdateSoftwareCursorTexture(index);
|
||||
|
||||
// Hide the system cursor when we activate a software cursor.
|
||||
if (is_hiding_or_showing && index == 0)
|
||||
InputManager::UpdateHostMouseMode();
|
||||
if (is_hiding_or_showing && index <= InputManager::MAX_POINTER_DEVICES)
|
||||
InputManager::UpdateRelativeMouseMode();
|
||||
}
|
||||
|
||||
bool ImGuiManager::HasSoftwareCursor(u32 index)
|
||||
|
|
|
@ -35,7 +35,7 @@ float GetWindowWidth();
|
|||
float GetWindowHeight();
|
||||
|
||||
/// Updates internal state when the window is size.
|
||||
void WindowResized();
|
||||
void WindowResized(float width, float height);
|
||||
|
||||
/// Updates scaling of the on-screen elements.
|
||||
void RequestScaleUpdate();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
|
||||
|
||||
#include "input_manager.h"
|
||||
#include "common/assert.h"
|
||||
|
@ -108,6 +108,7 @@ static std::vector<std::string_view> SplitChord(std::string_view binding);
|
|||
static bool SplitBinding(std::string_view binding, std::string_view* source, std::string_view* sub_binding);
|
||||
static void PrettifyInputBindingPart(std::string_view binding, SmallString& ret, bool& changed);
|
||||
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
|
||||
static void UpdatePointerCount();
|
||||
|
||||
static bool IsAxisHandler(const InputEventHandler& handler);
|
||||
static float ApplySingleBindingScale(float sensitivity, float deadzone, float value);
|
||||
|
@ -180,11 +181,19 @@ static std::array<std::array<float, static_cast<u8>(InputPointerAxis::Count)>, I
|
|||
static std::array<std::array<PointerAxisState, static_cast<u8>(InputPointerAxis::Count)>,
|
||||
InputManager::MAX_POINTER_DEVICES>
|
||||
s_pointer_state;
|
||||
static u32 s_pointer_count = 0;
|
||||
static std::array<float, static_cast<u8>(InputPointerAxis::Count)> s_pointer_axis_scale;
|
||||
|
||||
using PointerMoveCallback = std::function<void(InputBindingKey key, float value)>;
|
||||
static std::vector<std::pair<u32, PointerMoveCallback>> s_pointer_move_callbacks;
|
||||
|
||||
// Window size, used for clamping the mouse position in raw input modes.
|
||||
static std::array<float, 2> s_window_size = {};
|
||||
static bool s_relative_mouse_mode = false;
|
||||
static bool s_relative_mouse_mode_active = false;
|
||||
static bool s_hide_host_mouse_cursor = false;
|
||||
static bool s_hide_host_mouse_cusor_active = false;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Binding Parsing
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -293,12 +302,12 @@ bool InputManager::ParseBindingAndGetSource(std::string_view binding, InputBindi
|
|||
|
||||
std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key)
|
||||
{
|
||||
if (binding_type == InputBindingInfo::Type::Pointer)
|
||||
if (binding_type == InputBindingInfo::Type::Pointer || binding_type == InputBindingInfo::Type::AbsolutePointer)
|
||||
{
|
||||
// pointer and device bindings don't have a data part
|
||||
if (key.source_type == InputSourceType::Pointer)
|
||||
{
|
||||
return GetPointerDeviceName(key.data);
|
||||
return GetPointerDeviceName(key.source_index);
|
||||
}
|
||||
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
|
||||
{
|
||||
|
@ -346,7 +355,7 @@ std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type
|
|||
const InputBindingKey* keys, size_t num_keys)
|
||||
{
|
||||
// can't have a chord of devices/pointers
|
||||
if (binding_type == InputBindingInfo::Type::Pointer)
|
||||
if (binding_type == InputBindingInfo::Type::Pointer || binding_type == InputBindingInfo::Type::AbsolutePointer)
|
||||
{
|
||||
// so only take the first
|
||||
if (num_keys > 0)
|
||||
|
@ -598,10 +607,10 @@ static std::array<const char*, static_cast<u32>(InputSourceType::Count)> s_input
|
|||
#ifdef _WIN32
|
||||
"DInput",
|
||||
"XInput",
|
||||
"RawInput",
|
||||
#endif
|
||||
#ifndef __ANDROID__
|
||||
"SDL",
|
||||
"RawInput",
|
||||
#else
|
||||
"Android",
|
||||
#endif
|
||||
|
@ -631,13 +640,13 @@ bool InputManager::GetInputSourceDefaultEnabled(InputSourceType type)
|
|||
|
||||
case InputSourceType::XInput:
|
||||
return false;
|
||||
case InputSourceType::RawInput:
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#ifndef __ANDROID__
|
||||
case InputSourceType::SDL:
|
||||
return true;
|
||||
case InputSourceType::RawInput:
|
||||
return false;
|
||||
#else
|
||||
case InputSourceType::Android:
|
||||
return true;
|
||||
|
@ -844,6 +853,7 @@ void InputManager::AddPadBindings(SettingsInterface& si, const std::string& sect
|
|||
break;
|
||||
|
||||
case InputBindingInfo::Type::Pointer:
|
||||
case InputBindingInfo::Type::AbsolutePointer:
|
||||
{
|
||||
auto cb = [pad_index, base = bi.bind_index](InputBindingKey key, float value) {
|
||||
if (!System::IsValid())
|
||||
|
@ -867,7 +877,7 @@ void InputManager::AddPadBindings(SettingsInterface& si, const std::string& sect
|
|||
if (!key.has_value())
|
||||
continue;
|
||||
|
||||
s_pointer_move_callbacks.emplace_back(0, cb);
|
||||
s_pointer_move_callbacks.emplace_back(key.value(), cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1171,7 +1181,7 @@ void InputManager::GenerateRelativeMouseEvents()
|
|||
{
|
||||
const bool system_running = System::IsRunning();
|
||||
|
||||
for (u32 device = 0; device < MAX_POINTER_DEVICES; device++)
|
||||
for (u32 device = 0; device < s_pointer_count; device++)
|
||||
{
|
||||
for (u32 axis = 0; axis < static_cast<u32>(static_cast<u8>(InputPointerAxis::Count)); axis++)
|
||||
{
|
||||
|
@ -1208,14 +1218,44 @@ void InputManager::GenerateRelativeMouseEvents()
|
|||
}
|
||||
}
|
||||
|
||||
void InputManager::UpdatePointerCount()
|
||||
{
|
||||
if (!IsUsingRawInput())
|
||||
{
|
||||
s_pointer_count = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
InputSource* ris = GetInputSourceInterface(InputSourceType::RawInput);
|
||||
DebugAssert(ris);
|
||||
|
||||
s_pointer_count = 0;
|
||||
for (const std::pair<std::string, std::string>& it : ris->EnumerateDevices())
|
||||
{
|
||||
if (it.first.starts_with("Pointer-"))
|
||||
s_pointer_count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 InputManager::GetPointerCount()
|
||||
{
|
||||
return s_pointer_count;
|
||||
}
|
||||
|
||||
std::pair<float, float> InputManager::GetPointerAbsolutePosition(u32 index)
|
||||
{
|
||||
DebugAssert(index < s_host_pointer_positions.size());
|
||||
return std::make_pair(s_host_pointer_positions[index][static_cast<u8>(InputPointerAxis::X)],
|
||||
s_host_pointer_positions[index][static_cast<u8>(InputPointerAxis::Y)]);
|
||||
}
|
||||
|
||||
void InputManager::UpdatePointerAbsolutePosition(u32 index, float x, float y)
|
||||
{
|
||||
if (index >= MAX_POINTER_DEVICES || s_relative_mouse_mode_active) [[unlikely]]
|
||||
return;
|
||||
|
||||
const float dx = x - std::exchange(s_host_pointer_positions[index][static_cast<u8>(InputPointerAxis::X)], x);
|
||||
const float dy = y - std::exchange(s_host_pointer_positions[index][static_cast<u8>(InputPointerAxis::Y)], y);
|
||||
|
||||
|
@ -1236,18 +1276,26 @@ void InputManager::UpdatePointerAbsolutePosition(u32 index, float x, float y)
|
|||
|
||||
void InputManager::UpdatePointerRelativeDelta(u32 index, InputPointerAxis axis, float d, bool raw_input)
|
||||
{
|
||||
if (raw_input != IsUsingRawInput())
|
||||
if (index >= MAX_POINTER_DEVICES || !s_relative_mouse_mode_active)
|
||||
return;
|
||||
|
||||
s_host_pointer_positions[index][static_cast<u8>(axis)] += d;
|
||||
s_pointer_state[index][static_cast<u8>(axis)].delta.fetch_add(static_cast<s32>(d * 65536.0f),
|
||||
std::memory_order_release);
|
||||
|
||||
if (index == 0 && axis <= InputPointerAxis::Y)
|
||||
// We need to clamp the position ourselves in relative mode.
|
||||
if (axis <= InputPointerAxis::Y)
|
||||
{
|
||||
s_host_pointer_positions[index][static_cast<u8>(axis)] =
|
||||
std::clamp(s_host_pointer_positions[index][static_cast<u8>(axis)], 0.0f, s_window_size[static_cast<u8>(axis)]);
|
||||
|
||||
// Imgui also needs to be updated, since the absolute position won't be set above.
|
||||
if (index == 0)
|
||||
ImGuiManager::UpdateMousePosition(s_host_pointer_positions[0][0], s_host_pointer_positions[0][1]);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::UpdateHostMouseMode()
|
||||
void InputManager::UpdateRelativeMouseMode()
|
||||
{
|
||||
// Check for relative mode bindings, and enable if there's anything using it.
|
||||
bool has_relative_mode_bindings = !s_pointer_move_callbacks.empty();
|
||||
|
@ -1265,8 +1313,29 @@ void InputManager::UpdateHostMouseMode()
|
|||
}
|
||||
}
|
||||
|
||||
const bool has_software_cursor = ImGuiManager::HasSoftwareCursor(0);
|
||||
Host::SetMouseMode(has_relative_mode_bindings, has_relative_mode_bindings || has_software_cursor);
|
||||
const bool hide_mouse_cursor = has_relative_mode_bindings || ImGuiManager::HasSoftwareCursor(0);
|
||||
if (s_relative_mouse_mode == has_relative_mode_bindings && s_hide_host_mouse_cursor == hide_mouse_cursor)
|
||||
return;
|
||||
|
||||
s_relative_mouse_mode = has_relative_mode_bindings;
|
||||
s_hide_host_mouse_cursor = hide_mouse_cursor;
|
||||
UpdateRelativeMouseMode();
|
||||
}
|
||||
|
||||
void InputManager::UpdateHostMouseMode()
|
||||
{
|
||||
const bool can_change = System::IsRunning();
|
||||
const bool wanted_relative_mouse_mode = (s_relative_mouse_mode && can_change);
|
||||
const bool wanted_hide_host_mouse_cursor = (s_hide_host_mouse_cursor && can_change);
|
||||
if (wanted_relative_mouse_mode == s_relative_mouse_mode_active &&
|
||||
wanted_hide_host_mouse_cursor == s_hide_host_mouse_cusor_active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_relative_mouse_mode_active = wanted_relative_mouse_mode;
|
||||
s_hide_host_mouse_cusor_active = wanted_hide_host_mouse_cursor;
|
||||
Host::SetMouseMode(wanted_relative_mouse_mode, wanted_hide_host_mouse_cursor);
|
||||
}
|
||||
|
||||
bool InputManager::IsUsingRawInput()
|
||||
|
@ -1278,6 +1347,12 @@ bool InputManager::IsUsingRawInput()
|
|||
#endif
|
||||
}
|
||||
|
||||
void InputManager::SetDisplayWindowSize(float width, float height)
|
||||
{
|
||||
s_window_size[0] = width;
|
||||
s_window_size[1] = height;
|
||||
}
|
||||
|
||||
void InputManager::SetDefaultSourceConfig(SettingsInterface& si)
|
||||
{
|
||||
si.ClearSection("InputSources");
|
||||
|
@ -1454,11 +1529,13 @@ std::vector<std::string> InputManager::GetInputProfileNames()
|
|||
|
||||
void InputManager::OnInputDeviceConnected(std::string_view identifier, std::string_view device_name)
|
||||
{
|
||||
INFO_LOG("Device '{}' connected: '{}'", identifier, device_name);
|
||||
Host::OnInputDeviceConnected(identifier, device_name);
|
||||
}
|
||||
|
||||
void InputManager::OnInputDeviceDisconnected(InputBindingKey key, std::string_view identifier)
|
||||
{
|
||||
INFO_LOG("Device '{}' disconnected", identifier);
|
||||
Host::OnInputDeviceDisconnected(key, identifier);
|
||||
}
|
||||
|
||||
|
@ -1771,7 +1848,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
|
|||
1.0f);
|
||||
}
|
||||
|
||||
UpdateHostMouseMode();
|
||||
UpdateRelativeMouseMode();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -1788,6 +1865,8 @@ bool InputManager::ReloadDevices()
|
|||
changed |= s_input_sources[i]->ReloadDevices();
|
||||
}
|
||||
|
||||
UpdatePointerCount();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -1972,4 +2051,6 @@ void InputManager::ReloadSources(SettingsInterface& si, std::unique_lock<std::mu
|
|||
#else
|
||||
UpdateInputSourceState(si, settings_lock, InputSourceType::Android, &InputSource::CreateAndroidSource);
|
||||
#endif
|
||||
|
||||
UpdatePointerCount();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -27,10 +27,10 @@ enum class InputSourceType : u32
|
|||
#ifdef _WIN32
|
||||
DInput,
|
||||
XInput,
|
||||
RawInput,
|
||||
#endif
|
||||
#ifndef __ANDROID__
|
||||
SDL,
|
||||
RawInput,
|
||||
#else
|
||||
Android,
|
||||
#endif
|
||||
|
@ -174,12 +174,12 @@ namespace InputManager {
|
|||
static constexpr double VIBRATION_UPDATE_INTERVAL_SECONDS = 0.5; // 500ms
|
||||
|
||||
/// Maximum number of host mouse devices.
|
||||
static constexpr u32 MAX_POINTER_DEVICES = 1;
|
||||
static constexpr u32 MAX_POINTER_DEVICES = 8;
|
||||
static constexpr u32 MAX_POINTER_BUTTONS = 3;
|
||||
|
||||
/// Maximum number of software cursors. We allocate an extra two for controllers with
|
||||
/// positioning data from the controller instead of a mouse.
|
||||
static constexpr u32 MAX_SOFTWARE_CURSORS = MAX_POINTER_BUTTONS + 2;
|
||||
static constexpr u32 MAX_SOFTWARE_CURSORS = MAX_POINTER_DEVICES + 2;
|
||||
|
||||
/// Number of macro buttons per controller.
|
||||
static constexpr u32 NUM_MACRO_BUTTONS_PER_CONTROLLER = 4;
|
||||
|
@ -311,6 +311,9 @@ void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensi
|
|||
/// The pad vibration state will internally remain, so that when emulation is unpaused, the effect resumes.
|
||||
void PauseVibration();
|
||||
|
||||
/// Returns the number of currently-connected pointer devices.
|
||||
u32 GetPointerCount();
|
||||
|
||||
/// Reads absolute pointer position.
|
||||
std::pair<float, float> GetPointerAbsolutePosition(u32 index);
|
||||
|
||||
|
@ -322,6 +325,7 @@ void UpdatePointerAbsolutePosition(u32 index, float x, float y);
|
|||
void UpdatePointerRelativeDelta(u32 index, InputPointerAxis axis, float d, bool raw_input = false);
|
||||
|
||||
/// Updates host mouse mode (relative/cursor hiding).
|
||||
void UpdateRelativeMouseMode();
|
||||
void UpdateHostMouseMode();
|
||||
|
||||
/// Sets the state of the specified macro button.
|
||||
|
@ -330,6 +334,9 @@ void SetMacroButtonState(u32 pad, u32 index, bool state);
|
|||
/// Returns true if the raw input source is being used.
|
||||
bool IsUsingRawInput();
|
||||
|
||||
/// Updates InputManager's view of the window size, used for clamping raw input coordinates.
|
||||
void SetDisplayWindowSize(float width, float height);
|
||||
|
||||
/// Restores default configuration.
|
||||
void SetDefaultSourceConfig(SettingsInterface& si);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
|
||||
|
||||
#include "win32_raw_input_source.h"
|
||||
#include "common/assert.h"
|
||||
|
@ -8,7 +8,9 @@
|
|||
#include "core/host.h"
|
||||
#include "core/system.h"
|
||||
#include "input_manager.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <hidsdi.h>
|
||||
#include <hidusage.h>
|
||||
#include <malloc.h>
|
||||
|
||||
|
@ -71,7 +73,11 @@ void Win32RawInputSource::PollEvents()
|
|||
|
||||
std::vector<std::pair<std::string, std::string>> Win32RawInputSource::EnumerateDevices()
|
||||
{
|
||||
return {};
|
||||
std::vector<std::pair<std::string, std::string>> ret;
|
||||
for (u32 pointer_index = 0; pointer_index < static_cast<u32>(m_mice.size()); pointer_index++)
|
||||
ret.emplace_back(InputManager::GetPointerDeviceName(pointer_index), GetMouseDeviceName(pointer_index));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Win32RawInputSource::UpdateMotorState(InputBindingKey key, float intensity)
|
||||
|
@ -117,7 +123,8 @@ bool Win32RawInputSource::RegisterDummyClass()
|
|||
wc.hInstance = GetModuleHandleW(nullptr);
|
||||
wc.lpfnWndProc = DummyWindowProc;
|
||||
wc.lpszClassName = WINDOW_CLASS_NAME;
|
||||
return (RegisterClassW(&wc) != 0);
|
||||
s_window_class_registered = (RegisterClassW(&wc) != 0);
|
||||
return s_window_class_registered;
|
||||
}
|
||||
|
||||
bool Win32RawInputSource::CreateDummyWindow()
|
||||
|
@ -160,12 +167,58 @@ LRESULT CALLBACK Win32RawInputSource::DummyWindowProc(HWND hwnd, UINT msg, WPARA
|
|||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
std::string Win32RawInputSource::GetMouseDeviceName(u32 index)
|
||||
{
|
||||
#if 0
|
||||
// Doesn't work for mice :(
|
||||
const HANDLE device = m_mice[index].device;
|
||||
std::wstring wdevice_name;
|
||||
|
||||
UINT size = 0;
|
||||
if (GetRawInputDeviceInfoW(device, RIDI_DEVICENAME, nullptr, &size) == static_cast<UINT>(-1))
|
||||
goto error;
|
||||
|
||||
wdevice_name.resize(size);
|
||||
|
||||
UINT written_size = GetRawInputDeviceInfoW(device, RIDI_DEVICENAME, wdevice_name.data(), &size);
|
||||
if (written_size == static_cast<UINT>(-1))
|
||||
goto error;
|
||||
|
||||
wdevice_name.resize(written_size);
|
||||
if (wdevice_name.empty())
|
||||
goto error;
|
||||
|
||||
const HANDLE hFile = CreateFileW(wdevice_name.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
goto error;
|
||||
|
||||
wchar_t product_string[256];
|
||||
if (!HidD_GetProductString(hFile, product_string, sizeof(product_string)))
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
return StringUtil::WideStringToUTF8String(product_string);
|
||||
|
||||
error:
|
||||
return "Unknown Device";
|
||||
#else
|
||||
return fmt::format("Raw Input Pointer {}", index);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Win32RawInputSource::OpenDevices()
|
||||
{
|
||||
UINT num_devices = 0;
|
||||
if (GetRawInputDeviceList(nullptr, &num_devices, sizeof(RAWINPUTDEVICELIST)) == static_cast<UINT>(-1) ||
|
||||
num_devices == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<RAWINPUTDEVICELIST> devices(num_devices);
|
||||
if (GetRawInputDeviceList(devices.data(), &num_devices, sizeof(RAWINPUTDEVICELIST)) == static_cast<UINT>(-1))
|
||||
|
@ -174,28 +227,37 @@ bool Win32RawInputSource::OpenDevices()
|
|||
|
||||
for (const RAWINPUTDEVICELIST& rid : devices)
|
||||
{
|
||||
#if 0
|
||||
if (rid.dwType == RIM_TYPEKEYBOARD)
|
||||
m_num_keyboards++;
|
||||
#endif
|
||||
if (rid.dwType == RIM_TYPEMOUSE)
|
||||
m_mice.push_back({rid.hDevice, 0u, 0, 0});
|
||||
}
|
||||
|
||||
DEV_LOG("Found {} keyboards and {} mice", m_num_keyboards, m_mice.size());
|
||||
|
||||
// Grab all keyboard/mouse input.
|
||||
if (m_num_keyboards > 0)
|
||||
{
|
||||
const RAWINPUTDEVICE rrid = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, 0, m_dummy_window};
|
||||
if (!RegisterRawInputDevices(&rrid, 1, sizeof(rrid)))
|
||||
return false;
|
||||
// Make sure it's a real mouse with buttons.
|
||||
// My goal with this was to stop my silly Corsair keyboard from showing up as a mouse... but it reports 32
|
||||
// buttons.
|
||||
RID_DEVICE_INFO devinfo = {
|
||||
.cbSize = sizeof(devinfo),
|
||||
.dwType = RIM_TYPEMOUSE,
|
||||
};
|
||||
UINT devinfo_size = sizeof(devinfo);
|
||||
if (GetRawInputDeviceInfoW(rid.hDevice, RIDI_DEVICEINFO, &devinfo, &devinfo_size) <= 0 ||
|
||||
devinfo.mouse.dwNumberOfButtons == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_mice.push_back({.device = rid.hDevice, .button_state = 0, .last_x = 0, .last_y = 0});
|
||||
}
|
||||
}
|
||||
|
||||
DEV_LOG("Found {} mice", m_mice.size());
|
||||
|
||||
// Grab all mouse input.
|
||||
if (!m_mice.empty())
|
||||
{
|
||||
const RAWINPUTDEVICE rrid = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, 0, m_dummy_window};
|
||||
if (!RegisterRawInputDevices(&rrid, 1, sizeof(rrid)))
|
||||
return false;
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(m_mice.size()); i++)
|
||||
InputManager::OnInputDeviceConnected(InputManager::GetPointerDeviceName(i), GetMouseDeviceName(i));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -203,17 +265,16 @@ bool Win32RawInputSource::OpenDevices()
|
|||
|
||||
void Win32RawInputSource::CloseDevices()
|
||||
{
|
||||
if (m_num_keyboards > 0)
|
||||
{
|
||||
const RAWINPUTDEVICE rrid = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_REMOVE, m_dummy_window};
|
||||
RegisterRawInputDevices(&rrid, 1, sizeof(rrid));
|
||||
m_num_keyboards = 0;
|
||||
}
|
||||
|
||||
if (!m_mice.empty())
|
||||
{
|
||||
const RAWINPUTDEVICE rrid = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_REMOVE, m_dummy_window};
|
||||
RegisterRawInputDevices(&rrid, 1, sizeof(rrid));
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(m_mice.size()); i++)
|
||||
{
|
||||
InputManager::OnInputDeviceDisconnected(InputManager::MakePointerAxisKey(i, InputPointerAxis::X),
|
||||
InputManager::GetPointerDeviceName(i));
|
||||
}
|
||||
m_mice.clear();
|
||||
}
|
||||
}
|
||||
|
@ -222,9 +283,9 @@ bool Win32RawInputSource::ProcessRawInputEvent(const RAWINPUT* event)
|
|||
{
|
||||
if (event->header.dwType == RIM_TYPEMOUSE)
|
||||
{
|
||||
const u32 mouse_index = 0;
|
||||
for (MouseState& state : m_mice)
|
||||
for (u32 pointer_index = 0; pointer_index < static_cast<u32>(m_mice.size()); pointer_index++)
|
||||
{
|
||||
MouseState& state = m_mice[pointer_index];
|
||||
if (state.device != event->header.hDevice)
|
||||
continue;
|
||||
|
||||
|
@ -244,10 +305,6 @@ bool Win32RawInputSource::ProcessRawInputEvent(const RAWINPUT* event)
|
|||
(rm.usButtonFlags & (rm.usButtonFlags ^ std::exchange(state.button_state, rm.usButtonFlags))) &
|
||||
ALL_BUTTON_MASKS;
|
||||
|
||||
// when the VM isn't running, allow events to run as normal (so we don't break the UI)
|
||||
if (System::GetState() != System::State::Running)
|
||||
return false;
|
||||
|
||||
while (button_mask != 0)
|
||||
{
|
||||
unsigned long bit_index;
|
||||
|
@ -255,17 +312,17 @@ bool Win32RawInputSource::ProcessRawInputEvent(const RAWINPUT* event)
|
|||
|
||||
// these are ordered down..up for each button
|
||||
const u32 button_number = bit_index >> 1;
|
||||
const bool button_pressed = (bit_index & 1u) != 0;
|
||||
InputManager::InvokeEvents(InputManager::MakePointerButtonKey(mouse_index, button_number),
|
||||
const bool button_pressed = (bit_index & 1u) == 0;
|
||||
InputManager::InvokeEvents(InputManager::MakePointerButtonKey(pointer_index, button_number),
|
||||
static_cast<float>(button_pressed), GenericInputBinding::Unknown);
|
||||
|
||||
button_mask &= ~(1u << bit_index);
|
||||
}
|
||||
|
||||
if (dx != 0)
|
||||
InputManager::UpdatePointerRelativeDelta(mouse_index, InputPointerAxis::X, static_cast<float>(dx), true);
|
||||
InputManager::UpdatePointerRelativeDelta(pointer_index, InputPointerAxis::X, static_cast<float>(dx), true);
|
||||
if (dy != 0)
|
||||
InputManager::UpdatePointerRelativeDelta(mouse_index, InputPointerAxis::Y, static_cast<float>(dy), true);
|
||||
InputManager::UpdatePointerRelativeDelta(pointer_index, InputPointerAxis::Y, static_cast<float>(dy), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/windows_headers.h"
|
||||
|
@ -46,6 +46,8 @@ private:
|
|||
static bool RegisterDummyClass();
|
||||
static LRESULT CALLBACK DummyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static std::string GetMouseDeviceName(u32 index);
|
||||
|
||||
bool CreateDummyWindow();
|
||||
void DestroyDummyWindow();
|
||||
bool OpenDevices();
|
||||
|
@ -54,7 +56,6 @@ private:
|
|||
bool ProcessRawInputEvent(const RAWINPUT* event);
|
||||
|
||||
HWND m_dummy_window = {};
|
||||
u32 m_num_keyboards = 0;
|
||||
|
||||
std::vector<MouseState> m_mice;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue