mirror of https://github.com/PCSX2/pcsx2.git
USB-GunCon2: Support binding to controller
This commit is contained in:
parent
2703b91e41
commit
228f4f1010
|
@ -90,6 +90,8 @@ static std::vector<u8> s_standard_font_data;
|
|||
static std::vector<u8> s_fixed_font_data;
|
||||
static std::vector<u8> s_icon_font_data;
|
||||
|
||||
static float s_window_width;
|
||||
static float s_window_height;
|
||||
static Common::Timer s_last_render_time;
|
||||
|
||||
// cached copies of WantCaptureKeyboard/Mouse, used to know when to dispatch events
|
||||
|
@ -196,12 +198,24 @@ void ImGuiManager::Shutdown(bool clear_state)
|
|||
UnloadFontData();
|
||||
}
|
||||
|
||||
float ImGuiManager::GetWindowWidth()
|
||||
{
|
||||
return s_window_width;
|
||||
}
|
||||
|
||||
float ImGuiManager::GetWindowHeight()
|
||||
{
|
||||
return s_window_height;
|
||||
}
|
||||
|
||||
void ImGuiManager::WindowResized()
|
||||
{
|
||||
const u32 new_width = g_gs_device ? g_gs_device->GetWindowWidth() : 0;
|
||||
const u32 new_height = g_gs_device ? g_gs_device->GetWindowHeight() : 0;
|
||||
|
||||
ImGui::GetIO().DisplaySize = ImVec2(static_cast<float>(new_width), static_cast<float>(new_height));
|
||||
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);
|
||||
|
||||
UpdateScale();
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ namespace ImGuiManager
|
|||
/// Frees all ImGui resources.
|
||||
void Shutdown(bool clear_state);
|
||||
|
||||
/// Returns the size of the display window. Can be safely called from any thread.
|
||||
float GetWindowWidth();
|
||||
float GetWindowHeight();
|
||||
|
||||
/// Updates internal state when the window is size.
|
||||
void WindowResized();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "GS/GS.h"
|
||||
#include "Host.h"
|
||||
#include "ImGui/ImGuiManager.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
|
@ -26,6 +27,8 @@
|
|||
#include "USB/usb-lightgun/guncon2.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace usb_lightgun
|
||||
|
@ -52,6 +55,10 @@ namespace usb_lightgun
|
|||
BID_START = 15,
|
||||
BID_SHOOT_OFFSCREEN = 16,
|
||||
BID_RECALIBRATE = 17,
|
||||
BID_RELATIVE_LEFT = 18,
|
||||
BID_RELATIVE_RIGHT = 19,
|
||||
BID_RELATIVE_UP = 20,
|
||||
BID_RELATIVE_DOWN = 21,
|
||||
};
|
||||
|
||||
// Right pain in the arse. Different games seem to have different scales..
|
||||
|
@ -133,6 +140,7 @@ namespace usb_lightgun
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// Configuration
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool has_relative_binds = false;
|
||||
bool custom_config = false;
|
||||
u32 screen_width = 640;
|
||||
u32 screen_height = 240;
|
||||
|
@ -145,6 +153,10 @@ namespace usb_lightgun
|
|||
// Host State (Not Saved)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
u32 button_state = 0;
|
||||
std::string cursor_path;
|
||||
float cursor_scale = 1.0f;
|
||||
u32 cursor_color = 0xFFFFFFFF;
|
||||
float relative_pos[4] = {};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Device State (Saved)
|
||||
|
@ -162,6 +174,11 @@ namespace usb_lightgun
|
|||
void AutoConfigure();
|
||||
|
||||
std::tuple<s16, s16> CalculatePosition();
|
||||
|
||||
// 0..1, not -1..1.
|
||||
std::pair<float, float> GetAbsolutePositionFromRelativeAxes() const;
|
||||
u32 GetSoftwarePointerIndex() const;
|
||||
void UpdateSoftwarePointerPosition();
|
||||
};
|
||||
|
||||
static const USBDescStrings desc_strings = {
|
||||
|
@ -323,6 +340,10 @@ namespace usb_lightgun
|
|||
static void usb_hid_unrealize(USBDevice* dev)
|
||||
{
|
||||
GunCon2State* us = USB_CONTAINER_OF(dev, GunCon2State, dev);
|
||||
|
||||
if (!us->cursor_path.empty())
|
||||
ImGuiManager::ClearSoftwareCursor(us->GetSoftwarePointerIndex());
|
||||
|
||||
delete us;
|
||||
}
|
||||
|
||||
|
@ -359,8 +380,9 @@ namespace usb_lightgun
|
|||
std::tuple<s16, s16> GunCon2State::CalculatePosition()
|
||||
{
|
||||
float pointer_x, pointer_y;
|
||||
const std::pair<float, float> abs_pos(InputManager::GetPointerAbsolutePosition(0));
|
||||
GSTranslateWindowToDisplayCoordinates(abs_pos.first, abs_pos.second, &pointer_x, &pointer_y);
|
||||
const auto& [window_x, window_y] =
|
||||
(has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() : InputManager::GetPointerAbsolutePosition(0);
|
||||
GSTranslateWindowToDisplayCoordinates(window_x, window_y, &pointer_x, &pointer_y);
|
||||
|
||||
s16 pos_x, pos_y;
|
||||
if (pointer_x < 0.0f || pointer_y < 0.0f)
|
||||
|
@ -403,6 +425,29 @@ namespace usb_lightgun
|
|||
return std::tie(pos_x, pos_y);
|
||||
}
|
||||
|
||||
std::pair<float, float> GunCon2State::GetAbsolutePositionFromRelativeAxes() const
|
||||
{
|
||||
const float screen_rel_x = (((relative_pos[1] > 0.0f) ? relative_pos[1] : -relative_pos[0]) + 1.0f) * 0.5f;
|
||||
const float screen_rel_y = (((relative_pos[3] > 0.0f) ? relative_pos[3] : -relative_pos[2]) + 1.0f) * 0.5f;
|
||||
return std::make_pair(
|
||||
screen_rel_x * ImGuiManager::GetWindowWidth(), screen_rel_y * ImGuiManager::GetWindowHeight());
|
||||
}
|
||||
|
||||
u32 GunCon2State::GetSoftwarePointerIndex() const
|
||||
{
|
||||
return has_relative_binds ? (InputManager::MAX_POINTER_DEVICES + port) : 0;
|
||||
}
|
||||
|
||||
void GunCon2State::UpdateSoftwarePointerPosition()
|
||||
{
|
||||
pxAssert(has_relative_binds);
|
||||
if (cursor_path.empty())
|
||||
return;
|
||||
|
||||
const auto& [window_x, window_y] = GetAbsolutePositionFromRelativeAxes();
|
||||
ImGuiManager::SetSoftwareCursorPosition(GetSoftwarePointerIndex(), window_x, window_y);
|
||||
}
|
||||
|
||||
const char* GunCon2Device::Name() const
|
||||
{
|
||||
return TRANSLATE_NOOP("USB", "GunCon 2");
|
||||
|
@ -435,6 +480,8 @@ namespace usb_lightgun
|
|||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
|
||||
UpdateSettings(&s->dev, si);
|
||||
|
||||
return &s->dev;
|
||||
fail:
|
||||
usb_hid_unrealize(&s->dev);
|
||||
|
@ -457,6 +504,47 @@ namespace usb_lightgun
|
|||
s->scale_x = USB::GetConfigFloat(si, s->port, TypeName(), "scale_x", DEFAULT_SCALE_X) / 100.0f;
|
||||
s->scale_y = USB::GetConfigFloat(si, s->port, TypeName(), "scale_y", DEFAULT_SCALE_Y) / 100.0f;
|
||||
}
|
||||
|
||||
// Pointer settings.
|
||||
const std::string pointer_binding = USB::GetConfigString(si, s->port, TypeName(), "Pointer", "");
|
||||
std::string cursor_path(USB::GetConfigString(si, s->port, TypeName(), "cursor_path"));
|
||||
const float cursor_scale = USB::GetConfigFloat(si, s->port, TypeName(), "cursor_scale", 1.0f);
|
||||
u32 cursor_color = 0xFFFFFF;
|
||||
if (std::string cursor_color_str(USB::GetConfigString(si, s->port, TypeName(), "cursor_color")); !cursor_color_str.empty())
|
||||
{
|
||||
// Strip the leading hash, if it's a CSS style colour.
|
||||
const std::optional<u32> cursor_color_opt(
|
||||
StringUtil::FromChars<u32>(cursor_color_str[0] == '#' ?
|
||||
std::string_view(cursor_color_str).substr(1) : std::string_view(cursor_color_str), 16));
|
||||
if (cursor_color_opt.has_value())
|
||||
cursor_color = cursor_color_opt.value();
|
||||
}
|
||||
|
||||
const s32 prev_pointer_index = s->GetSoftwarePointerIndex();
|
||||
|
||||
s->has_relative_binds = (USB::ConfigKeyExists(si, s->port, TypeName(), "RelativeLeft") ||
|
||||
USB::ConfigKeyExists(si, s->port, TypeName(), "RelativeRight") ||
|
||||
USB::ConfigKeyExists(si, s->port, TypeName(), "RelativeUp") ||
|
||||
USB::ConfigKeyExists(si, s->port, TypeName(), "RelativeDown"));
|
||||
|
||||
const s32 new_pointer_index = s->GetSoftwarePointerIndex();
|
||||
|
||||
if (prev_pointer_index != new_pointer_index || s->cursor_path != cursor_path ||
|
||||
s->cursor_scale != cursor_scale || s->cursor_color != cursor_color)
|
||||
{
|
||||
if (prev_pointer_index != new_pointer_index)
|
||||
ImGuiManager::ClearSoftwareCursor(prev_pointer_index);
|
||||
|
||||
// Pointer changed, so need to update software cursor.
|
||||
if (!cursor_path.empty())
|
||||
ImGuiManager::SetSoftwareCursor(new_pointer_index, cursor_path, cursor_scale, cursor_color);
|
||||
else if (!s->cursor_path.empty())
|
||||
ImGuiManager::ClearSoftwareCursor(new_pointer_index);
|
||||
|
||||
s->cursor_path = std::move(cursor_path);
|
||||
s->cursor_scale = cursor_scale;
|
||||
s->cursor_color = cursor_color;
|
||||
}
|
||||
}
|
||||
|
||||
float GunCon2Device::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||
|
@ -471,11 +559,23 @@ namespace usb_lightgun
|
|||
{
|
||||
GunCon2State* s = USB_CONTAINER_OF(dev, GunCon2State, dev);
|
||||
|
||||
const u32 bit = 1u << bind_index;
|
||||
if (value >= 0.5f)
|
||||
s->button_state |= bit;
|
||||
else
|
||||
s->button_state &= ~bit;
|
||||
if (bind_index < BID_RELATIVE_LEFT)
|
||||
{
|
||||
const u32 bit = 1u << bind_index;
|
||||
if (value >= 0.5f)
|
||||
s->button_state |= bit;
|
||||
else
|
||||
s->button_state &= ~bit;
|
||||
}
|
||||
else if (bind_index <= BID_RELATIVE_DOWN)
|
||||
{
|
||||
const u32 rel_index = bind_index - BID_RELATIVE_LEFT;
|
||||
if (s->relative_pos[rel_index] != value)
|
||||
{
|
||||
s->relative_pos[rel_index] = value;
|
||||
s->UpdateSoftwarePointerPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::span<const InputBindingInfo> GunCon2Device::Bindings(u32 subtype) const
|
||||
|
@ -497,6 +597,10 @@ namespace usb_lightgun
|
|||
{"C", TRANSLATE_NOOP("USB", "C"), InputBindingInfo::Type::Button, BID_C, GenericInputBinding::Triangle},
|
||||
{"Select", TRANSLATE_NOOP("USB", "Select"), InputBindingInfo::Type::Button, BID_SELECT, GenericInputBinding::Select},
|
||||
{"Start", TRANSLATE_NOOP("USB", "Start"), InputBindingInfo::Type::Button, BID_START, GenericInputBinding::Start},
|
||||
{"RelativeLeft", TRANSLATE_NOOP("USB", "Relative Left"), InputBindingInfo::Type::HalfAxis, BID_RELATIVE_LEFT, GenericInputBinding::Unknown},
|
||||
{"RelativeRight", TRANSLATE_NOOP("USB", "Relative Right"), InputBindingInfo::Type::HalfAxis, BID_RELATIVE_RIGHT, GenericInputBinding::Unknown},
|
||||
{"RelativeUp", TRANSLATE_NOOP("USB", "Relative Up"), InputBindingInfo::Type::HalfAxis, BID_RELATIVE_UP, GenericInputBinding::Unknown},
|
||||
{"RelativeDown", TRANSLATE_NOOP("USB", "Relative Down"), InputBindingInfo::Type::HalfAxis, BID_RELATIVE_DOWN, GenericInputBinding::Unknown},
|
||||
};
|
||||
|
||||
return bindings;
|
||||
|
@ -505,16 +609,27 @@ namespace usb_lightgun
|
|||
std::span<const SettingInfo> GunCon2Device::Settings(u32 subtype) const
|
||||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{SettingInfo::Type::Path, "cursor_path", "Cursor Path",
|
||||
TRANSLATE_NOOP("USB", "Sets the crosshair image that this lightgun will use. Setting a crosshair image "
|
||||
"will disable the system cursor."),
|
||||
""},
|
||||
{SettingInfo::Type::Float, "cursor_scale", TRANSLATE_NOOP("USB", "Cursor Scale"),
|
||||
TRANSLATE_NOOP("USB", "Scales the crosshair image set above."), "1", "0.01", "10", "0.01", "%.0f%%",
|
||||
nullptr, nullptr, 100.0f},
|
||||
{SettingInfo::Type::String, "cursor_color", TRANSLATE_NOOP("USB", "Cursor Color"),
|
||||
TRANSLATE_NOOP("USB", "Applys a color to the chosen crosshair images, can be used for multiple "
|
||||
"players. Specify in HTML/CSS format (e.g. #aabbcc)"),
|
||||
"#ffffff"},
|
||||
{SettingInfo::Type::Boolean, "custom_config", TRANSLATE_NOOP("USB", "Manual Screen Configuration"),
|
||||
TRANSLATE_NOOP("USB",
|
||||
"Forces the use of the screen parameters below, instead of automatic parameters if available."),
|
||||
"false"},
|
||||
{SettingInfo::Type::Float, "scale_x", TRANSLATE_NOOP("USB", "X Scale (Sensitivity)"),
|
||||
"Scales the position to simulate CRT curvature.", "100", "0", "200", "0.1", "%.2f%%", nullptr, nullptr,
|
||||
1.0f},
|
||||
TRANSLATE_NOOP("USB", "Scales the position to simulate CRT curvature."), "100", "0", "200", "0.1",
|
||||
"%.2f%%", nullptr, nullptr, 1.0f},
|
||||
{SettingInfo::Type::Float, "scale_y", TRANSLATE_NOOP("USB", "Y Scale (Sensitivity)"),
|
||||
"Scales the position to simulate CRT curvature.", "100", "0", "200", "0.1", "%.2f%%", nullptr, nullptr,
|
||||
1.0f},
|
||||
TRANSLATE_NOOP("USB", "Scales the position to simulate CRT curvature."), "100", "0", "200", "0.1",
|
||||
"%.2f%%", nullptr, nullptr, 1.0f},
|
||||
{SettingInfo::Type::Float, "center_x", TRANSLATE_NOOP("USB", "Center X"),
|
||||
TRANSLATE_NOOP("USB", "Sets the horizontal center position of the simulated screen."), "320", "0",
|
||||
"1024", "1", "%.0fpx", nullptr, nullptr, 1.0f},
|
||||
|
|
Loading…
Reference in New Issue