Skip to content

Commit

Permalink
Input: Add "Left-handed Controller Inputs" option
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jan 7, 2024
1 parent 5fa064e commit e2e5d39
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 52 deletions.
114 changes: 72 additions & 42 deletions src/mods/VR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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<vr::VRInputValueHandle_t, 2> {
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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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>(((float)state->Gamepad.sThumbLX + left_joystick_axis.x * 32767.0f), -32767.0f, 32767.0f);
state->Gamepad.sThumbLY = (int16_t)std::clamp<float>(((float)state->Gamepad.sThumbLY + left_joystick_axis.y * 32767.0f), -32767.0f, 32767.0f);
Expand All @@ -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;
}
}
}
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -941,15 +969,15 @@ 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;
state->Gamepad.sThumbLX = 0;
}
}
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;
Expand Down Expand Up @@ -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());
}
}

Expand Down Expand Up @@ -2220,14 +2248,15 @@ 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();
}

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();
Expand Down Expand Up @@ -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{};
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 12 additions & 2 deletions src/mods/VR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
21 changes: 13 additions & 8 deletions src/mods/vr/OverlayComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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});
Expand Down Expand Up @@ -852,8 +855,9 @@ std::optional<std::reference_wrapper<XrCompositionLayerQuad>> 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});
Expand Down Expand Up @@ -1067,8 +1071,9 @@ std::optional<std::reference_wrapper<XrCompositionLayerQuad>> 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});
Expand Down

1 comment on commit e2e5d39

@JibJab1980
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should change your name to praygod, absolute legend thank you !!!!!!!!!!!

Please sign in to comment.