diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index eb4b8690..2333adc0 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -833,27 +833,56 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE // Touching the thumbrest allows us to use the thumbstick as a dpad if (m_thumbrest_shifting->value()) { const auto a_b_touch_inactive = !is_action_active_any_joystick(m_action_a_button_touch_right) && !is_action_active_any_joystick(m_action_b_button_touch_right); - const auto thumbrest_active = a_b_touch_inactive && is_action_active_any_joystick(m_action_thumbrest_touch_right); + bool thumbrest_check_L; + bool thumbrest_check_R; + DPadMethod dpad_method = get_dpad_method(); + if (dpad_method == DPadMethod::RIGHT_TOUCH || DPadMethod::BOTH) { + thumbrest_check_R = is_action_active_any_joystick(m_action_thumbrest_touch_right); + } + if (dpad_method == DPadMethod::LEFT_TOUCH || DPadMethod::BOTH) { + thumbrest_check_L = is_action_active_any_joystick(m_action_thumbrest_touch_left); + } + + const auto thumbrest_active = a_b_touch_inactive && (thumbrest_check_R || thumbrest_check_L); if (thumbrest_active) { - if (state->Gamepad.sThumbLY >= 16383) { + 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 (thumbrest_check_R) { + ThumbY = state->Gamepad.sThumbLY; + ThumbX = state->Gamepad.sThumbLX; + } + else if (thumbrest_check_L) { + ThumbY = state->Gamepad.sThumbRY; + ThumbX = state->Gamepad.sThumbRX; + } + + if (ThumbY >= 16383) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; } - if (state->Gamepad.sThumbLY <= -16383) { + if (ThumbY <= -16383) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; } - if (state->Gamepad.sThumbLX >= 16383) { + if (ThumbX >= 16383) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; } - if (state->Gamepad.sThumbLX <= -16383) { + if (ThumbX <= -16383) { state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; } - state->Gamepad.sThumbLY = 0; - state->Gamepad.sThumbLX = 0; + if (thumbrest_check_R) { + state->Gamepad.sThumbLY = 0; + state->Gamepad.sThumbLX = 0; + } + else if (thumbrest_check_L) { + state->Gamepad.sThumbRY = 0; + state->Gamepad.sThumbRX = 0; + } + } } @@ -1969,10 +1998,16 @@ void VR::on_draw_ui() { m_uncap_framerate->draw("Uncap Framerate"); m_enable_gui->draw("Enable GUI"); m_enable_depth->draw("Enable Depth"); - m_thumbrest_shifting->draw("Thumbrest DPad Shifting"); m_load_blueprint_code->draw("Load Blueprint Code"); m_ghosting_fix->draw("Ghosting Fix"); + ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); + if (ImGui::TreeNode("Thumbrest DPad Shifting")) { + m_thumbrest_shifting->draw("Enabled"); + m_thumbrest_shifting_method->draw("Method"); + ImGui::TreePop(); + } + ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Splitscreen Compatibility")) { m_splitscreen_compatibility_mode->draw("Enabled"); @@ -2029,6 +2064,17 @@ void VR::on_draw_ui() { ImGui::TreePop(); } + ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); + if (ImGui::TreeNode("Snap Turn")) { + m_snapturn->draw("Enabled"); + ImGui::Text("Set Snap Turn Rotation Degrees."); + m_snapturn_degrees->draw("Degrees"); + ImGui::Text("Set Snap Turn Joystick Deadzone."); + m_snapturn_joystick_deadzone->draw("Deadzone"); + + ImGui::TreePop(); + } + ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Decoupled Pitch")) { m_decoupled_pitch->draw("Enabled"); diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index 35033544..ad1daed9 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -45,6 +45,12 @@ class VR : public Mod { TWO_HANDED_LEFT, }; + enum DPadMethod : int32_t { + RIGHT_TOUCH, + LEFT_TOUCH, + BOTH, + }; + static const inline std::string s_action_pose = "/actions/default/in/Pose"; static const inline std::string s_action_grip_pose = "/actions/default/in/GripPose"; static const inline std::string s_action_trigger = "/actions/default/in/Trigger"; @@ -455,6 +461,22 @@ class VR : public Mod { return m_roomscale_movement_actor_rotation->value(); } + DPadMethod get_dpad_method() const { + return (DPadMethod)m_thumbrest_shifting_method->value(); + } + + bool is_snapturn_enabled() const { + return m_snapturn->value(); + } + + float get_snapturn_js_deadzone() const { + return m_snapturn_joystick_deadzone->value(); + } + + int get_snapturn_degrees() const { + return m_snapturn_degrees->value(); + } + bool should_skip_post_init_properties() const { return m_compatibility_skip_pip->value(); } @@ -656,6 +678,12 @@ class VR : public Mod { "Two Handed (Left)", }; + static const inline std::vector s_dpad_method_names { + "Right Thumbrest + Left Joystick", + "Left Thumbrest + Right Joystick", + "Both Thumbrests + Opposite Joystick (Incompatible with SnapTurn)", + }; + const ModCombo::Ptr m_rendering_method{ ModCombo::create(generate_name("RenderingMethod"), s_rendering_method_names) }; const ModCombo::Ptr m_synced_afr_method{ ModCombo::create(generate_name("SyncedSequentialMethod"), s_synced_afr_method_names, 1) }; const ModToggle::Ptr m_uncap_framerate{ ModToggle::create(generate_name("UncapFramerate"), true) }; @@ -671,6 +699,9 @@ class VR : public Mod { 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_roomscale_movement_actor_rotation{ ModToggle::create(generate_name("RoomscaleMovementActorRotation"), false) }; + const ModToggle::Ptr m_snapturn{ ModToggle::create(generate_name("SnapTurn"), false) }; + const ModSlider::Ptr m_snapturn_joystick_deadzone{ ModSlider::create(generate_name("SnapturnJoystickDeadzone"), 0.01f, 0.9f, 0.1f) }; + const ModInt32::Ptr m_snapturn_degrees{ ModInt32::create(generate_name("SnapturnTurnDegrees"), 45) }; // Aim method and movement orientation are not the same thing, but they can both have the same options const ModCombo::Ptr m_aim_method{ ModCombo::create(generate_name("AimMethod"), s_aim_method_names, AimMethod::GAME) }; @@ -679,6 +710,7 @@ class VR : public Mod { const ModToggle::Ptr m_aim_interp{ ModToggle::create(generate_name("AimInterp"), true) }; const ModSlider::Ptr m_aim_speed{ ModSlider::create(generate_name("AimSpeed"), 0.01f, 25.0f, 15.0f) }; const ModToggle::Ptr m_thumbrest_shifting{ ModToggle::create(generate_name("ThumbrestShifting"), true) }; + const ModCombo::Ptr m_thumbrest_shifting_method{ ModCombo::create(generate_name("ThumbrestShiftingMethod"), s_dpad_method_names, DPadMethod::RIGHT_TOUCH) }; //const ModToggle::Ptr m_headlocked_aim{ ModToggle::create(generate_name("HeadLockedAim"), false) }; //const ModToggle::Ptr m_headlocked_aim_controller_based{ ModToggle::create(generate_name("HeadLockedAimControllerBased"), false) }; @@ -738,11 +770,15 @@ class VR : public Mod { *m_2d_screen_mode, *m_roomscale_movement, *m_roomscale_movement_actor_rotation, + *m_snapturn, + *m_snapturn_joystick_deadzone, + *m_snapturn_degrees, *m_aim_method, *m_movement_orientation, *m_aim_speed, *m_aim_interp, *m_thumbrest_shifting, + *m_thumbrest_shifting_method, *m_motion_controls_inactivity_timer, *m_joystick_deadzone, *m_camera_forward_offset,