bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
35.95k stars 3.55k forks source link

`cargo run --example gamepad_input` not getting `RightTrigger2` on linux #5240

Open bcolloran opened 2 years ago

bcolloran commented 2 years ago

What went wrong

RightTrigger2 input is not logged when trying the cargo run --example gamepad_input example on linux. Gampad verified to be working (all axes, triggers, buttons) via https://greggman.github.io/html5-gamepad-test/

Bevy version

(just pulled latest)

$ git branch
* latest
  main
$ git rev-parse `git branch | cut -d' ' -f2`
83c6ffb73c4a91182cda10141f824987ef3fba2f

Relevant system information

System

Release Linux Mint 20.1 Ulyssa 64-bit
Kernel Linux 5.4.0-121-generic x86_64
MATE 1.24.0

cargo:

$ cargo --version
cargo 1.60.0 (d1fd9fe 2022-03-01)

What you did

Ran cargo run --example gamepad_input, and tried pressing all the buttons and wiggling the sticks on the gamepad.

Here are the first several lines of output when I run the example

$ cargo run --example gamepad_input
   Compiling bevy v0.7.0 (/.../rust/bevy)
    Finished dev [unoptimized + debuginfo] target(s) in 28.25s
     Running `target/debug/examples/gamepad_input`
2022-07-07T01:56:36.470600Z  INFO winit::platform_impl::platform::x11::window: Guessed window scale factor: 1    
2022-07-07T01:56:36.589375Z  INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce RTX 2060", vendor: 4318, device: 7944, device_type: DiscreteGpu, backend: Vulkan }
2022-07-07T01:56:38.608285Z  INFO gilrs_core::platform::platform::gamepad: Gamepad /dev/input/event5 (Generic X-Box pad) connected.    
2022-07-07T01:56:38.614346Z  INFO bevy_input::gamepad: Gamepad(0) Connected
2022-07-07T01:56:40.328713Z  INFO gamepad_input: Gamepad(0) LeftStickX value is 0.22946167
2022-07-07T01:56:40.345702Z  INFO gamepad_input: Gamepad(0) LeftStickX value is 0.24337769
alice-i-cecile commented 2 years ago

What gamepad are you using? This is probably an upstream bug in gilrs.

bcolloran commented 2 years ago

It's an XBox Wireless Controller.

Sorry if I've filed this in the wrong place! Does anyone on the bevy team have permissions to transfer the issue over there? (I can file it manually if not)

bcolloran commented 2 years ago

(fwiw while we sort out the right place for this issue)--

using: axes.get(GamepadAxis(gamepad, GamepadAxisType::RightZ)) with axes: Res<Axis<GamepadAxis>>

rather than: button_axes.get(GamepadButton(gamepad, GamepadButtonType::RightTrigger)) with button_axes: Res<Axis<GamepadButton>> does the trick for getting the trigger analog values.

(the gamepad_input example uses the latter)

alice-i-cecile commented 2 years ago

Ah! Looks like #5220 but for triggers. This is probably not terribly hardware specific, and is mostly our problem.

We should look to see if the same style of fix can be applied.

RaddHazard commented 2 years ago

On bevy 0.8.1 I have the same issue. With all of the following controllers: -wired XBox One -wired XBox 360 -wired and wireless dualshock 4 (PS4) -wired and wireless dual sense (PS5) (the playstation controllers are using ds4windows so they show up as xinput devices, specifically 360 controllers I believe)

The issue is the same in all cases. Left and right stick analog values report correctly but right and left triggers only act as buttons (analog values for RightZ and LeftZ are always 0.0).

I am using:

using: axes.get(GamepadAxis(gamepad, GamepadAxisType::RightZ)) with axes: Res<Axis>

as @bcolloran mentioned.

Carlrs commented 2 years ago

For what it's worth, I couldn't reproduce it until I updated my xpadneo driver to the latest version which mostly consists of this product code change I believe.

Basically, old version: SteamInput messed up, input in Bevy works. New version: SteamInput works, input in Bevy messed up.

alice-i-cecile commented 2 years ago

@Carlrs, I suspect gilrs was working around a bad driver. Can you open an issue upstream?

rdelfin commented 1 year ago

From what I've been testing, wired XBox One controller seems to be working fine now in bevy 0.9.1 (haven't tested earlier versions). I did see a few issues in the gilrs repo that are tangentially related and have been fixed by the latest version of gilrs, as used by latest bevy. @RaddHazard: is this also fixed for you?

RaddHazard commented 1 year ago

@rdelfin Updated quickly and it looks like I have the same problem. Triggers only working as buttons, no analog values.

geophree commented 1 year ago

I fell into a rabbit hole on this one a little bit... hopefully something in here is useful.

TL;DR: My understanding is that button_axes.get(GamepadButton(gamepad, GamepadButtonType::RightTrigger2)) (notice the 2) with button_axes: Res<Axis<GamepadButton>> is the correct way to get the trigger's analog value in bevy. GamepadButtonType::RightTrigger (no 2) is the right bumper on xbox 360 controllers.

My investigation (see "Research" section) leads me to believe that (at least on linux) GamepadAxisType::LeftZ and GamepadAxisType::RightZ are supposed to be representing a 3rd dimension for the left and right stick. Looking around, I think this may be used for joysticks that can also twist.

In reality, I think different gamepad drivers do different things, some map triggers to LeftZ/RightZ. Then gilrs (using SDL gamecontrollerdb.txt) remaps them to the "right" place, as analog buttons. So if you're seeing trigger values in LeftZ/RightZ, it's probably missing or misconfigured in SDL gamecontrollerdb.txt: https://github.com/gabomdq/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt


To see some more info about what gilrs is doing with your controller:

Add to Cargo.toml:

[dependencies]
gilrs = "0.10"
uuid = "1.3"

Put in an existing rust file and app.add_system(output_gamepad):

use gilrs::{Axis, Button, Gilrs};
use uuid::Uuid;

fn output_gamepad(gilrs: NonSend<Gilrs>, mut printed: Local<bool>, mut counter: Local<u8>) {
    if !*printed {
        // This is *not* the right way to interact with gamepads in bevy, you shouldn't be using gilrs directly.
        for (_, gamepad) in gilrs.gamepads() {
            println!("uuid: {:?}", Uuid::from_bytes(gamepad.uuid()));
            println!("uuid (no '-'): {:?}", Uuid::from_bytes(gamepad.uuid()).to_string().replace("-", ""));
            println!("os_name: {:?}", gamepad.os_name());
            println!("map_name: {:?}", gamepad.map_name());
            println!("mapping_source: {:?}", gamepad.mapping_source());
            println!("LeftZ maps to: {:?}", gamepad.axis_code(Axis::LeftZ));
            *printed = true;
        }
    }

    *counter = (*counter).wrapping_add(1);
    if *counter % 60 == 0 {
        for (_, gamepad) in gilrs.gamepads() {
            // This is *not* the right way to get theses values in bevy, you shouldn't be using gilrs directly.
            println!("LT: {:?}", gamepad.button_data(Button::LeftTrigger).map(|b| b.value()));
            println!("LT2: {:?}", gamepad.button_data(Button::LeftTrigger2).map(|b| b.value()));
        }
    }
}

The output for my Microsoft Xbox 360 Wireless Controller on linux:

uuid: 03000000-5e04-0000-a102-000000010000
uuid (no '-'): "030000005e040000a102000000010000"
os_name: "Xbox 360 Wireless Receiver"
map_name: Some("Xbox 360 Controller")
mapping_source: SdlMappings
LeftZ maps to: None
LT: None
LT2: None
LT: None
LT2: Some(0.85490197)
LT: None
LT2: Some(0.77254903)
LT: None
LT2: Some(0.627451)
LT: None
LT2: Some(1.0)
LT: None
LT2: Some(1.0)
LT: None
LT2: Some(0.0)

Searching for the uuid in https://github.com/gabomdq/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt gets me:

030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,

Note the Linux at the end, this mapping will only be used by gilrs when building on linux (technically: "unix that's not Android and not MacOSX", so maybe BSDs and such as well?). See https://gitlab.com/gilrs-project/gilrs/-/blob/master/gilrs/build.rs .

"Research"

https://github.com/bevyengine/bevy/blob/75da2e7adfb025e443ce83cf917225a67e147161/crates/bevy_gilrs/src/converter.rs#L36

https://gitlab.com/gilrs-project/gilrs/-/blob/b17de7da57485c41595c17990965e1ad7b7a2c56/gilrs/src/mapping/mod.rs#L108 maps gilrs_core::native_ev_codes::AXIS_LEFTZ to gilrs::Axis::LeftZ

https://gitlab.com/gilrs-project/gilrs/-/blob/7cd001dacfb188405e5e41520912a259367a4703/gilrs-core/src/lib.rs#L304 defines gilrs_core::native_ev_codes::AXIS_LEFTZ as gilrs_core::platform::native_ev_codes::AXIS_LEFTZ

When compiled on linux:

https://gitlab.com/gilrs-project/gilrs/-/blob/7cd001dacfb188405e5e41520912a259367a4703/gilrs-core/src/platform/linux/gamepad.rs#L1117-1120 defines gilrs_core::platform::native_ev_codes::AXIS_LEFTZ as ABS_Z

https://gitlab.com/gilrs-project/gilrs/-/blob/7cd001dacfb188405e5e41520912a259367a4703/gilrs-core/src/platform/linux/gamepad.rs#L1012 defines ABS_Z as 0x02

https://github.com/torvalds/linux/blob/9f4211bf7f811b653aa6acfb9aea38222436a458/include/uapi/linux/input-event-codes.h#L844 Also defines ABS_Z as 0x02

https://www.kernel.org/doc/html/v6.3/input/event-codes.html?highlight=abs_z#ev-abs Says: "If the input device may be used freely in three dimensions, consider ABS_Z instead."

cstegel commented 6 months ago

Thank you @geophree!

I can confirm button_axes.get(GamepadButton(gamepad, GamepadButtonType::RightTrigger2)) with button_axes: Res<Axis<GamepadButton>> works for wired Xbox 360 controller in Bevy 0.13.2.