Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Can't used a joystick that is connected in the middle of program execution.  (Read 7136 times)

0 Members and 1 Guest are viewing this topic.

hechelion

  • Newbie
  • *
  • Posts: 24
    • View Profile
I encountered a problem when trying to use a gamepad or joystick that is connected in the middle of program execution.

I have this minimum code:
Code: [Select]
// See https://aka.ms/new-console-template for more information
//Console.WriteLine("Hello, World!");

using System;
using SFML.Audio;
using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace sfml
{
    class Program
    {
        static void Main(string[] args)
        {
            string TITULO = "Test Input";
            string VERSION = "0.0.1";
     
            //Selección estilo de ventana
            Styles auxStyle = Styles.Default;

            //Creamos el objeto windows
            RenderWindow window = new RenderWindow(new VideoMode(800, 600), TITULO + "  v " + VERSION, auxStyle);
            window.Closed += (_, __) => window.Close();           
            window.JoystickConnected += (o, e) => gamePad_connect(e);
            window.JoystickDisconnected += (o, e) => gamePad_disconnect(e);
           

            //Variable propias de este contexto, como color de renderwindow o auxiliares para shader
            Color backColor = new Color(0,0,255); //Color de fondo

            Joystick.Update();

            int Joystickcount = 0;
            for(uint i=0;i<8;i++){
                if (Joystick.IsConnected(i)) { Joystickcount++; }
            }
            Console.WriteLine("Total de Joystick: " + Joystickcount.ToString());

            //Ciclo principal
            while (window.IsOpen)
            {

                //***** Rutinas especiales como actualizacíon de gamepad *****
                Joystick.Update();
                int newJoystickcount = 0;
                for(uint i=0;i<8;i++){
                    if (Joystick.IsConnected(i)) { newJoystickcount++; }
                }
                if (newJoystickcount != Joystickcount) {
                    Joystickcount = newJoystickcount;
                    Console.WriteLine("Total de Joystick: " + Joystickcount.ToString());
                }
                if (Joystick.IsButtonPressed(0,0)) { Console.WriteLine("Joystick 0, button 0 "); }
           
                window.DispatchEvents(); //Control de eventos
                window.Clear(backColor); //Limpiamos la pantalla con el color de fondo seleccionado
             
                window.Display();
            }

        }

        static void gamePad_connect(JoystickConnectEventArgs e){
            Console.WriteLine("Joystick " + e.JoystickId.ToString() + "conectado");
        }
        static void gamePad_disconnect(JoystickConnectEventArgs e){
             Console.WriteLine("Joystick " + e.JoystickId.ToString() + "desconectado");
        }
    }
}

If I have a joystick connected and I run the application, it is detected and can be used without problem.

If in the middle of the execution I disconnect the joystick, the disconnection is detected, the number of connected joystick is updated.
then i reconnect the joystick, the connection is detected, the number of connected joystick is back to 1 and i can use the joystick again, so far everything works as expected.

The console output:
Quote
Total de Joystick: 1
1661 Joystick 0, botón 0
Total de Joystick: 0
Joystick 0 desconectado
21 Failed to create DirectInput device: -2147467259
578 Failed to create DirectInput device: -2147221164
Total de Joystick: 1
Joystick 0 conectado
554 Joystick 0, botón 0
The program '[10288] test_input.dll' has exited with code 0 (0x0).


***************************************
The problem occurs when I launch the app without the joystick connected.

If, during the execution of the program, I connect the joystick, you can see that it actually triggers the "JoystickConnected" event. But I don't have access, since all the joysticks of "Joystick.IsConnected" mark false.
I have tried to force read with
"if (Joystick.IsButtonPressed(0,0)) { Console.WriteLine("Joystick 0, button 0 "); }"

But it doesn't work, it's like SFML detects that the joystick was connected, but doesn't give access to it.

Quote
Total de Joystick: 0
Joystick 0 conectado
Joystick 0 desconectado
14
Failed to create DirectInput device: -2147467259
Joystick 0 conectado
The program '[4728] test_input.dll' has exited with code 0 (0x0).

Is it necessary to do something to be able to access the Joystick or is it a bug?


Spec
Windows 10.
C#
Code: [Select]
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SFML.Net" Version="2.5.0" />
  </ItemGroup>

</Project>

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Have you tried sf::Joystick::update()?
Not sure if this could affect this since it says it updates automatically when there's a window.

Note: I've just checked with something and if I disconnect the joystick after starting with it already connected, I get a similar DirectInput error (it goes away when re-connected but only because everything is still set up to use it). It's not exactly the same issue but it's a similar error so it may be connected.
(I'm using C++ btw)
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

hechelion

  • Newbie
  • *
  • Posts: 24
    • View Profile
Hi.
If you look at the source code, you'll see that "Joystick.update()" is called every loop.

Also, in my tests, the "DirectInput" error occurs precisely when I call "Joystick.update()".

EDIT:
In C# if you don't call Joystick.update() every loop, SFML doesn't refresh the value of the gamepad input.
« Last Edit: February 16, 2023, 11:41:46 pm by hechelion »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
In C# if you don't call Joystick.update() every loop, SFML doesn't refresh the value of the gamepad input.
Yeah, it's an issue with having SFML linked statically into CSFML and thus the singleton fails to be a singleton.

The mentioned DirectInput errors are a bit odd, as the returned error codes lead to some old XP issues.
You can web search these: 0x80004005 / 0x80040154
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

hechelion

  • Newbie
  • *
  • Posts: 24
    • View Profile
Thanks for your answer eXpl0it3r.

I understand the root of the problem, but I'm not sure how to fix it.

I want to point out, my problem is that I do NOT have access to the joystick, even using Joystick.Update() in each loop, if the joystick is not connected from the start of the application (I highlight this part, because it is the condition that leads to the error )

I comment on this, because in the issue they wrote this:
"Unless I manually update the joystick state before the calls."
If I understand correctly, this refers to calling "Joystick.Update()", but again, I called Joystick.Update and still don't have access to the joystick.
Which makes me doubt that it is exactly the same problem.

It also read "I changed window to regular sfWindow (instead of sfRenderWindow)", but I don't know how to replicate this in C# with Net 6.0

I understand recompiling SFML with the proper flags, but I'd have to study how to compile SFML for Net 6.0 and before doing that, I'd like to make sure it's the same error.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
I don't have much experience with the joystick API, but I did just recently get a xbox controller, so I'll test some behavior sometime soon.

It also read "I changed window to regular sfWindow (instead of sfRenderWindow)", but I don't know how to replicate this in C# with Net 6.0
Not sure if it can be done in SFML.Net, but SFML.Graphics.RenderWindow derives from SFML.Window.Window, which should then use sfWindow, so maybe it can be casted?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

hechelion

  • Newbie
  • *
  • Posts: 24
    • View Profile
Sorry I didn't answer sooner, but my laptop was stolen.
Right now I only have a linux machine, I installed c# and SFML, but I get random errors, so I think I'll migrate to C++ to be able to develop under linux.

Thank you very much for your time and answers.

smurf

  • Newbie
  • *
  • Posts: 36
    • View Profile
Resurrecting this thread because I have the exact same issue and I don't see a solution yet.
Launching a game and then turning your controller on is an extremely common scenario so this bug is a big deal IMHO.
Every single time I'm having to restart the game because I forgot to turn on the controller first.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
If you're still talking about CSFML / SFML.Net then yes, the issue isn't really "solved".

You can see the respective issues on the CSFML and SFML.Net repositories.

Copy pasting the comment I added the other day:

Quote
Since it came up in discussions again on Discord, I drew up this diagram highlighting the issue.



I guess there are two options:
  • Don't link SFML statically and ship the specific DLLs as well (we do this on other platforms already)
  • Inversion of control. Instead of having the singleton being updated by the event loop and thus missing updates if there are multiple instance in different DLLs, we would need to change it so the Joystick class can query the information on its own.

Current workarounds:
  • Cast/use sfWindow functions
  • Manually call update

I believe we don't really have a choice but to change how we ship CSFML and provide SFML as DLLs in the future as well.
« Last Edit: June 05, 2024, 07:59:58 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

smurf

  • Newbie
  • *
  • Posts: 36
    • View Profile
Thank you for the information.

Honestly I'm a bit confused why calling update manually keeps being proposed as a workaround. It does not work. Also I'm calling Joystick.Update() every frame anyway, so I wouldn't even call it a workaround, I would be completely happy with it.

Anyway I guess I'll keep an eye out for updates. Thanks!