kniEngine / kni

KNI is a cross-platform C# game framework.
Other
128 stars 9 forks source link

Gamepads do not report as connected, and buttons are not read from gamepads #1759

Closed vchelaru closed 1 week ago

vchelaru commented 1 month ago

I have recently updated to 3.13.9001 and am testing gamepad integration. For testing, I have created a brand new project and only modified the Update method as shown in the following code:

TimeSpan lastUpdateCall = TimeSpan.Zero;

protected override void Update(GameTime gameTime)
{
    // to prevent spamming of output
    if((gameTime.TotalGameTime - lastUpdateCall).TotalSeconds > 1)
    {
        lastUpdateCall = gameTime.TotalGameTime;
        Console.WriteLine($"At {lastUpdateCall}");
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.One), "One"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Two), "Two"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Three), "Three"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Four), "Four"));

        Console.WriteLine();
    }

    string GetStatusFor(GamePadState state, string name)
    {
        var isA = state.Buttons.A;
        var isB = state.Buttons.B;
        var isX = state.Buttons.X;
        var isY = state.Buttons.Y;

        return $"{name}:{state.IsConnected} A:{isA} B:{isB} X:{isX} Y:{isY}";
    }

    base.Update(gameTime);
}

I am testing this with two controllers:

image

Note that the lights are turned on for both of them.

If I launch the game, and I go to the console output, I see the following in Chrome, Edge, and Firefox:

image

However, if I unplug and plug the switch controller while the app is running, then one of the controllers shows up as being connected:

image

At one point it was "one" and at another it was "two" so it may have to do with the indexes assigned by the USB ports, but I'm not sure.

However, no matter what, whether it returns true or false for connected, the A button is always reported as Released even if I press all of the buttons on both gamepads when connected is true.

If there's anything else I can do to help diagnose this issue, please let me know.

What version of KNI does the bug occur on:

What operating system are you using:

What KNI platform are you using:

nkast commented 1 month ago

One limitation of web browsers is that they will not report connected devices from the start for security reasons (fingerprinting). The devices will be 'connected' as soon as there is an interaction from the user like pressing a button or connecting the device.

The A button worked when I tested it, Is the problem with both controllers?

vchelaru commented 1 month ago

The problem is with just one controller, but the results that I'm getting are inconsistent from project to project. It's very strange.

I suppose I should simplify the question and ask - if you plugin 2 gamepads, do both show up as connected?

nkast commented 1 month ago

In theory yes. But the only case I tested it was with a non recognized joystick and an xbox controller. I have a bluetooth xbox somewhere... when I found it I could test both on my laptop. In theory, both controllers should show up as soon as one of them has a user input.

An improvement would be to do what SDL does and assign our own index to each controller. Right now, if a non-standard joystick is connected first, and later you connect an xbox controller, the xbox is shown as PlayerIndex.Two.

nkast commented 1 month ago

So you are getting either the xbox, or the switch connected, at random?

edit Try this page to see if you are getting any different results. https://hardwaretester.com/gamepad

vchelaru commented 1 month ago

Thank you for the diagnostics website you sent, it's super helpful in telling me if it's a problem on my end with the gamepad/USB/etc. It looks like my gamepad is detected immediately and all input is read correctly from the hardware tester site, but the Kni project does not detect. Here's a gif of the output and the hardware tester page:

26_07 28 25

And here's the Game class I'm using in case you want to try to replicate it:

GraphicsDeviceManager graphics;

public GamepadTestGame()
{
    graphics = new GraphicsDeviceManager(this);
}

TimeSpan lastUpdateCall = TimeSpan.Zero;
protected override void Update(GameTime gameTime)
{
    // to prevent spamming of output
    if ((gameTime.TotalGameTime - lastUpdateCall).TotalSeconds > 1)
    {
        lastUpdateCall = gameTime.TotalGameTime;
        Console.WriteLine($"At {lastUpdateCall}");
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.One), "One"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Two), "Two"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Three), "Three"));
        Console.WriteLine(GetStatusFor(GamePad.GetState(PlayerIndex.Four), "Four"));
        Console.WriteLine();
    }

    string GetStatusFor(GamePadState state, string name)
    {
        var isA = state.Buttons.A;
        var isB = state.Buttons.B;
        var isX = state.Buttons.X;
        var isY = state.Buttons.Y;
        return $"{name}:{state.IsConnected} A:{isA} B:{isB} X:{isX} Y:{isY}";
    }
    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    base.Draw(gameTime);
}

I simplified the situation by having only the Nintendo Switch controller plugged in.

nkast commented 1 month ago

The problem here is that the gamepad is not recognized by the browser. A properly recognized gamepad will have mapping set to 'standard' and have 17 buttons and 4 axes.

https://w3c.github.io/gamepad/#remapping The specs also state that "Devices that are not recognized should still be exposed in their raw form." There is not much we can do with the information provided by those devices. We can only expose those devices from the Joystick API.

@vchelaru, Does that gamepad work on DesktopGL projects? If it does ,then it's because DSL has it's own mappings (https://github.com/mdqinc/SDL_GameControllerDB).
That's also not much use, because the browser will not report the device GUID.

vchelaru commented 1 month ago

Yes, the gamepad does work in DesktopGL projects.

However, what I'm unclear on is - if the gamepad is not recognized by the browser, then why does it show up as a gamepad in the hardwaretester.com page that you linked?

nkast commented 1 week ago

I am closing this as there is nothing to do on our part. It's in the hands of web browsers to extend the recognized set of gamepads. Right now only Xbox controllers and a couple of official alternatives are supported.