From e2e5d39801a482bc27defebc470dfb72fdb57b65 Mon Sep 17 00:00:00 2001 From: praydog Date: Sat, 6 Jan 2024 21:22:44 -0800 Subject: [PATCH] Input: Add "Left-handed Controller Inputs" option --- src/mods/VR.cpp | 114 +++++++++++++++++++------------ src/mods/VR.hpp | 14 +++- src/mods/vr/OverlayComponent.cpp | 21 +++--- 3 files changed, 97 insertions(+), 52 deletions(-) diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index 69b03004..866081f2 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -646,6 +646,9 @@ bool VR::is_any_action_down() { return true; } + const auto left_joystick = get_left_joystick(); + const auto right_joystick = get_right_joystick(); + for (auto& it : m_action_handles) { // These are too easy to trigger if (it.second == m_action_thumbrest_touch_left || it.second == m_action_thumbrest_touch_right) { @@ -660,7 +663,7 @@ bool VR::is_any_action_down() { continue; } - if (is_action_active(it.second, m_left_joystick) || is_action_active(it.second, m_right_joystick)) { + if (is_action_active(it.second, left_joystick) || is_action_active(it.second, right_joystick)) { return true; } } @@ -758,16 +761,18 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.sThumbRY = 0; } - const auto joysticks = std::array { - m_right_joystick, - m_left_joystick - }; + const auto left_joystick = get_left_joystick(); + const auto right_joystick = get_right_joystick(); + const auto wants_swap = m_swap_controllers->value(); runtime->handle_pause_select(is_action_active_any_joystick(m_action_system_button)); do_pause_select(); - const auto is_right_a_button_down = is_action_active_any_joystick(m_action_a_button_right); - const auto is_left_a_button_down = is_action_active_any_joystick(m_action_a_button_left); + const auto& a_button_left = !wants_swap ? m_action_a_button_left : m_action_a_button_right; + const auto& a_button_right = !wants_swap ? m_action_a_button_right : m_action_a_button_left; + + const auto is_right_a_button_down = is_action_active_any_joystick(a_button_right); + const auto is_left_a_button_down = is_action_active_any_joystick(a_button_left); if (is_right_a_button_down) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_A; @@ -777,8 +782,11 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_B; } - const auto is_right_b_button_down = is_action_active_any_joystick(m_action_b_button_right); - const auto is_left_b_button_down = is_action_active_any_joystick(m_action_b_button_left); + const auto& b_button_left = !wants_swap ? m_action_b_button_left : m_action_b_button_right; + const auto& b_button_right = !wants_swap ? m_action_b_button_right : m_action_b_button_left; + + const auto is_right_b_button_down = is_action_active_any_joystick(b_button_right); + const auto is_left_b_button_down = is_action_active_any_joystick(b_button_left); if (is_right_b_button_down) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_X; @@ -788,8 +796,8 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_Y; } - const auto is_left_joystick_click_down = is_action_active(m_action_joystick_click, m_left_joystick); - const auto is_right_joystick_click_down = is_action_active(m_action_joystick_click, m_right_joystick); + const auto is_left_joystick_click_down = is_action_active(m_action_joystick_click, left_joystick); + const auto is_right_joystick_click_down = is_action_active(m_action_joystick_click, right_joystick); if (is_left_joystick_click_down) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; @@ -799,8 +807,8 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; } - const auto is_left_trigger_down = is_action_active(m_action_trigger, m_left_joystick); - const auto is_right_trigger_down = is_action_active(m_action_trigger, m_right_joystick); + const auto is_left_trigger_down = is_action_active(m_action_trigger, left_joystick); + const auto is_right_trigger_down = is_action_active(m_action_trigger, right_joystick); if (is_left_trigger_down) { state->Gamepad.bLeftTrigger = 255; @@ -810,8 +818,8 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.bRightTrigger = 255; } - const auto is_right_grip_down = is_action_active(m_action_grip, m_right_joystick); - const auto is_left_grip_down = is_action_active(m_action_grip, m_left_joystick); + const auto is_right_grip_down = is_action_active(m_action_grip, right_joystick); + const auto is_left_grip_down = is_action_active(m_action_grip, left_joystick); if (is_right_grip_down) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; @@ -845,8 +853,11 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; } - const auto left_joystick_axis = get_joystick_axis(m_left_joystick); - const auto right_joystick_axis = get_joystick_axis(m_right_joystick); + const auto left_joystick_axis = get_joystick_axis(left_joystick); + const auto right_joystick_axis = get_joystick_axis(right_joystick); + + const auto true_left_joystick_axis = get_joystick_axis(m_left_joystick); + const auto true_right_joystick_axis = get_joystick_axis(m_right_joystick); state->Gamepad.sThumbLX = (int16_t)std::clamp(((float)state->Gamepad.sThumbLX + left_joystick_axis.x * 32767.0f), -32767.0f, 32767.0f); state->Gamepad.sThumbLY = (int16_t)std::clamp(((float)state->Gamepad.sThumbLY + left_joystick_axis.y * 32767.0f), -32767.0f, 32767.0f); @@ -872,41 +883,57 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE const auto dpad_active = (button_touch_inactive && thumbrest_check) || dpad_method == DPadMethod::LEFT_JOYSTICK || dpad_method == DPadMethod::RIGHT_JOYSTICK; if (dpad_active) { - SHORT ThumbY{0}; - SHORT ThumbX{0}; + float ty{0.0f}; + float tx{0.0f}; + //SHORT ThumbY{0}; + //SHORT ThumbX{0}; // If someone is accidentally touching both thumbrests while also moving a joystick, this will default to left joystick. if (dpad_method == DPadMethod::RIGHT_TOUCH || dpad_method == DPadMethod::LEFT_JOYSTICK) { - ThumbY = state->Gamepad.sThumbLY; - ThumbX = state->Gamepad.sThumbLX; + //ThumbY = state->Gamepad.sThumbLY; + //ThumbX = state->Gamepad.sThumbLX; + ty = true_left_joystick_axis.y; + tx = true_left_joystick_axis.x; } else if (dpad_method == DPadMethod::LEFT_TOUCH || dpad_method == DPadMethod::RIGHT_JOYSTICK) { - ThumbY = state->Gamepad.sThumbRY; - ThumbX = state->Gamepad.sThumbRX; + //ThumbY = state->Gamepad.sThumbRY; + //ThumbX = state->Gamepad.sThumbRX; + ty = true_right_joystick_axis.y; + tx = true_right_joystick_axis.x; } - if (ThumbY >= 16383) { + if (ty >= 0.5f) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; } - if (ThumbY <= -16383) { + if (ty <= -0.5f) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; } - if (ThumbX >= 16383) { + if (tx >= 0.5f) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; } - if (ThumbX <= -16383) { + if (tx <= -0.5f) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; } if (dpad_method == DPadMethod::RIGHT_TOUCH || dpad_method == DPadMethod::LEFT_JOYSTICK) { - state->Gamepad.sThumbLY = 0; - state->Gamepad.sThumbLX = 0; + if (!wants_swap) { + state->Gamepad.sThumbLY = 0; + state->Gamepad.sThumbLX = 0; + } else { + state->Gamepad.sThumbRY = 0; + state->Gamepad.sThumbRX = 0; + } } else if (dpad_method == DPadMethod::LEFT_TOUCH || dpad_method == DPadMethod::RIGHT_JOYSTICK) { - state->Gamepad.sThumbRY = 0; - state->Gamepad.sThumbRX = 0; + if (!wants_swap) { + state->Gamepad.sThumbRY = 0; + state->Gamepad.sThumbRX = 0; + } else { + state->Gamepad.sThumbLY = 0; + state->Gamepad.sThumbLX = 0; + } } } } @@ -916,10 +943,10 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE DPadMethod dpad_method = get_dpad_method(); const auto snapturn_deadzone = get_snapturn_js_deadzone(); float stick_axis{}; - + if (!m_was_snapturn_run_on_input) { if (dpad_method == RIGHT_JOYSTICK) { - stick_axis = get_left_stick_axis().x; + stick_axis = true_left_joystick_axis.x; if (glm::abs(stick_axis) >= snapturn_deadzone) { if (stick_axis < 0) { m_snapturn_left = true; @@ -929,8 +956,9 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE } } else { - stick_axis = get_right_stick_axis().x; - if (glm::abs(stick_axis) >= snapturn_deadzone && !(dpad_method == DPadMethod::LEFT_TOUCH && is_action_active_any_joystick(m_action_thumbrest_touch_left))) { + stick_axis = right_joystick_axis.x; + const auto& thumbrest_touch_left = !wants_swap ? m_action_thumbrest_touch_left : m_action_thumbrest_touch_right; + if (glm::abs(stick_axis) >= snapturn_deadzone && !(dpad_method == DPadMethod::LEFT_TOUCH && is_action_active_any_joystick(thumbrest_touch_left))) { if (stick_axis < 0) { m_snapturn_left = true; } @@ -941,7 +969,7 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE } else { if (dpad_method == RIGHT_JOYSTICK) { - if (glm::abs(get_left_stick_axis().x) < snapturn_deadzone) { + if (glm::abs(true_left_joystick_axis.x) < snapturn_deadzone) { m_was_snapturn_run_on_input = false; } else { state->Gamepad.sThumbLY = 0; @@ -949,7 +977,7 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE } } else { - if (glm::abs(get_right_stick_axis().x) < snapturn_deadzone) { + if (glm::abs(right_joystick_axis.x) < snapturn_deadzone) { m_was_snapturn_run_on_input = false; } else { state->Gamepad.sThumbRY = 0; @@ -978,11 +1006,11 @@ void VR::on_xinput_set_state(uint32_t* retval, uint32_t user_index, XINPUT_VIBRA const auto right_amplitude = ((float)vibration->wRightMotorSpeed / 65535.0f) * 5.0f; if (left_amplitude > 0.0f) { - trigger_haptic_vibration(0.0f, 0.1f, 1.0f, left_amplitude, m_left_joystick); + trigger_haptic_vibration(0.0f, 0.1f, 1.0f, left_amplitude, get_left_joystick()); } if (right_amplitude > 0.0f) { - trigger_haptic_vibration(0.0f, 0.1f, 1.0f, right_amplitude, m_right_joystick); + trigger_haptic_vibration(0.0f, 0.1f, 1.0f, right_amplitude, get_right_joystick()); } } @@ -2220,6 +2248,8 @@ void VR::on_draw_sidebar_entry(std::string_view name) { if (ImGui::TreeNode("Controller")) { m_joystick_deadzone->draw("VR Joystick Deadzone"); m_dpad_shifting->draw("DPad Shifting"); + ImGui::SameLine(); + m_swap_controllers->draw("Left-handed Controller Inputs"); m_dpad_shifting_method->draw("DPad Shifting Method"); ImGui::TreePop(); @@ -2227,7 +2257,6 @@ void VR::on_draw_sidebar_entry(std::string_view name) { ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Aim Method")) { - ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Experimental, may crash"); ImGui::TextWrapped("Some games may not work with this enabled."); if (m_aim_method->draw("Type")) { m_previous_aim_method = (AimMethod)m_aim_method->value(); @@ -2865,6 +2894,7 @@ Vector2f VR::get_joystick_axis(vr::VRInputValueHandle_t handle) const { return out; } else if (get_runtime()->is_openxr()) { + // Not using get_left/right_joystick here because it flips the controllers if (handle == m_left_joystick) { auto out = m_openxr->get_left_stick_axis(); //return glm::length(out) > m_joystick_deadzone->value() ? out : Vector2f{}; @@ -2898,11 +2928,11 @@ Vector2f VR::get_joystick_axis(vr::VRInputValueHandle_t handle) const { } Vector2f VR::get_left_stick_axis() const { - return get_joystick_axis(m_left_joystick); + return get_joystick_axis(get_left_joystick()); } Vector2f VR::get_right_stick_axis() const { - return get_joystick_axis(m_right_joystick); + return get_joystick_axis(get_right_joystick()); } void VR::trigger_haptic_vibration(float seconds_from_now, float duration, float frequency, float amplitude, vr::VRInputValueHandle_t source) { diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index 0c031059..98a33d02 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -310,11 +310,19 @@ class VR : public Mod { } auto get_left_joystick() const { - return m_left_joystick; + if (!m_swap_controllers->value()) { + return m_left_joystick; + } + + return m_right_joystick; } auto get_right_joystick() const { - return m_right_joystick; + if (!m_swap_controllers->value()) { + return m_right_joystick; + } + + return m_left_joystick; } bool is_gui_enabled() const { @@ -765,6 +773,7 @@ class VR : public Mod { const ModToggle::Ptr m_load_blueprint_code{ ModToggle::create(generate_name("LoadBlueprintCode"), false, true) }; const ModToggle::Ptr m_2d_screen_mode{ ModToggle::create(generate_name("2DScreenMode"), false) }; const ModToggle::Ptr m_roomscale_movement{ ModToggle::create(generate_name("RoomscaleMovement"), false) }; + const ModToggle::Ptr m_swap_controllers{ ModToggle::create(generate_name("SwapControllerInputs"), false) }; // Snap turn settings and globals void process_snapturn(); @@ -876,6 +885,7 @@ class VR : public Mod { *m_load_blueprint_code, *m_2d_screen_mode, *m_roomscale_movement, + *m_swap_controllers, *m_snapturn, *m_snapturn_joystick_deadzone, *m_snapturn_angle, diff --git a/src/mods/vr/OverlayComponent.cpp b/src/mods/vr/OverlayComponent.cpp index c885dd38..1a26d7f0 100644 --- a/src/mods/vr/OverlayComponent.cpp +++ b/src/mods/vr/OverlayComponent.cpp @@ -118,7 +118,8 @@ void OverlayComponent::update_input_mouse_emulation() { static bool was_pressing_right = false; // Left click. - if (VR::get()->is_action_active_any_joystick(vr->get_action_handle(VR::s_action_a_button_right))) { + const auto& a_button_right = !vr->m_swap_controllers->value() ? VR::s_action_a_button_right : VR::s_action_a_button_left; + if (VR::get()->is_action_active_any_joystick(vr->get_action_handle(a_button_right))) { // Clear any gamepad A events. auto ctx = io.Ctx; @@ -141,7 +142,8 @@ void OverlayComponent::update_input_mouse_emulation() { } // Right click. - if (VR::get()->is_action_active_any_joystick(vr->get_action_handle(VR::s_action_b_button_right))) { + const auto& b_button_right = !vr->m_swap_controllers->value() ? VR::s_action_b_button_right : VR::s_action_b_button_left; + if (VR::get()->is_action_active_any_joystick(vr->get_action_handle(b_button_right))) { // Clear any gamepad B events. auto ctx = io.Ctx; @@ -733,8 +735,9 @@ void OverlayComponent::update_overlay_openvr() { // Check if the controller pointer intersects with the quad, and we can use this to emulate the mouse if (vr->is_using_controllers()) { // Right only for now for testing - const auto right_controller_rot = glm::quat{vr->get_rotation(vr->get_right_controller_index(), false)}; - const auto right_controller_pos = glm::vec3{vr->get_position(vr->get_right_controller_index(), false)}; + const auto controller_index = !vr->m_swap_controllers->value() ? vr->get_right_controller_index() : vr->get_left_controller_index(); + const auto right_controller_rot = glm::quat{vr->get_rotation(controller_index, false)}; + const auto right_controller_pos = glm::vec3{vr->get_position(controller_index, false)}; const auto start = right_controller_pos; auto fwd = (right_controller_rot * glm::vec3{0.0f, 0.0f, -1.0f}); @@ -852,8 +855,9 @@ std::optional> OverlayComponent:: // Check if the controller pointer intersects with the quad, and we can use this to emulate the mouse if (vr->is_using_controllers()) { // Right only for now for testing - const auto right_controller_rot = glm::quat{vr->get_rotation(vr->get_right_controller_index(), false)}; - const auto right_controller_pos = glm::vec3{vr->get_position(vr->get_right_controller_index(), false)}; + const auto controller_index = !vr->m_swap_controllers->value() ? vr->get_right_controller_index() : vr->get_left_controller_index(); + const auto right_controller_rot = glm::quat{vr->get_rotation(controller_index, false)}; + const auto right_controller_pos = glm::vec3{vr->get_position(controller_index, false)}; const auto start = right_controller_pos; auto fwd = (right_controller_rot * glm::vec3{0.0f, 0.0f, -1.0f}); @@ -1067,8 +1071,9 @@ std::optional> OverlayComponent:: // Check if the controller pointer intersects with the quad, and we can use this to emulate the mouse if (vr->is_using_controllers()) { // Right only for now for testing - const auto right_controller_rot = glm::quat{vr->get_rotation(vr->get_right_controller_index(), false)}; - const auto right_controller_pos = glm::vec3{vr->get_position(vr->get_right_controller_index(), false)}; + const auto controller_index = !vr->m_swap_controllers->value() ? vr->get_right_controller_index() : vr->get_left_controller_index(); + const auto right_controller_rot = glm::quat{vr->get_rotation(controller_index, false)}; + const auto right_controller_pos = glm::vec3{vr->get_position(controller_index, false)}; const auto start = right_controller_pos; auto fwd = (right_controller_rot * glm::vec3{0.0f, 0.0f, -1.0f});