CSFML
CSFML copied to clipboard
Joystick state does not update when polling events via RenderWindow on Windows
Hi,
The joystick state does not seem to get updated properly on Windows.
According to the tutorial, "Joystick states are automatically updated when you check for events”, which I assume means that they got updated when the window is polling events. Doc on sfJoystick_update as well as the official sfml joystick example also work as suggested.
However when testing the following code with CSFML 2.5, calls to sfJoystick_isConnected always return false, unless I manually update the joystick state before the calls.
sfRenderWindow* window = sfRenderWindow_create(mode, "joystick test", sfClose, NULL);
printf("Before polling:\n");
for (int i = 0; i < sfJoystickCount; ++i) {
// sfJoystick_update();
sfBool connected = sfJoystick_isConnected(i);
printf("%d: %d\n", i, connected);
}
printf("Polling starts:\n");
while(sfRenderWindow_isOpen(window)) {
sfEvent evt;
while(sfRenderWindow_pollEvent(window, &evt)) {
//sfJoystick_update();
if (evt.type == sfEvtClosed) {
sfRenderWindow_close(window);
break;
}
else if (evt.type == sfEvtJoystickMoved) {
//sfJoystick_update();
unsigned int id = evt.joystickMove.joystickId;
printf("%d: %d\n", id, sfJoystick_isConnected(id));
}
}
}
I am building the above code with CSFML 2.5 64bit, mingw gcc 8.1 on windows 7. The joystick used is a compatible XBOX controller. Similar code in c++ with SFML 2.5.1 runs without issue, however. I also tested the code on mac and it worked as intended, so I'd suspect it's a windows only issue?
EDIT: Ok here is the funny part... when I changed window to regular sfWindow (instead of sfRenderWindow) I got the expected behavior.
Any insights would be appreciated.
Thanks for reporting this issue!
Maybe it's not propagates to the correct C++ class/pointer. Requires further investigation.
I have been having the same problem with SFML on .Net. After some investigation I realized that building SFML with the flag BUILD_SHARED_LIBS=1 and SFML_USE_STATIC_STD_LIBS=0 and then building CSML with the flag CSFML_LINK_SFML_STATICALLY=0 makes this sample work as expected (I have been using tools\nuget\build.win.ps1 to build). You can check that in my fork.
I've built CSFML source code using the current flags on that file and with the proposed flags, wrote the equivalent piece of code as my issue on SFML.Net in C, C++ and C# and linked using these files and these are the results:
-
Building SFML with BUILD_SHARED_LIBS=0, SFML_USE_STATIC_STD_LIBS=1 and CSFML with CSFML_LINK_SFML_STATICALLY=1 C++: work as expected C: doesn't detect joystick update unless calling sfJoystick_update() each loop C#: doesn't detect joystick update unless calling Joystick.Update() each loop
-
Building SFML with BUILD_SHARED_LIBS=1, SFML_USE_STATIC_STD_LIBS=0 and CSFML with CSFML_LINK_SFML_STATICALLY=0 C++: work as expected C: work as expected C#: work as expected
So it looks like the problem lies in linking to SFML statically. I'll keep on investigating this issue, but if someone has some insight on this it would be greatly appreciated, since I don't have a lot of experience with C, C++, CMake and the whole dynamic\static binding stuff.
Ok, I'm getting somewhere.
When SFML is linked statically, the JoystickManager singleton is actually not a singleton (JoystickManager& JoystickManager::getInstance()), but a different copy for each CSML dll. What ends up happening here is that RenderWindow is located on csfml-graphics-d.dll, while all Joystick calls are located on csfml-window-d.dll. So when the RenderWindow calls JoystickManager.update() it is actually using a different instance of JoystickManager than when accessing the Joystick state.
That's why using Window instead of RenderWindow will make it work fine, since Window is a part of csfml-window-d.dll. Also, calling sfJoystick_update( ) will work as well.
This is the same problem being discussed here. I'll see if I can find a solution that's not simply always linking to SFML dynamically on Windows.