Joystick support via SDL2 library?

Hi,

i try the existing joystick support plugin and wonder why this is done via DirectX/XInput/Win API etc. instead of using multiplattform working SDL2 library ?

I do some test with sdl2 get the joystick input working through using and rewriting code of the exiting joystick plugin. This seems to work.
Unfortunately, I failed to get working the correct paths to the lib/dll (of my self compiled SDL2) for the build scripts. My hack was copying the .dll to the binary/win64 directory, which is obviously not the correct way (why there is, as one and only, an autodesk fbx.dll …) - but this works for testing. I think this may a good way…joystick and more via SDL2 not only on linux also on windows.

So my question is it possible to add per default on all plattforms the SDL2 libraries and dll´s to the dependencies ?

tom

A SDL based joystick bind would be a welcome addition, interested to see this in action.

Regarding dlls, in the plugins I’ve bound, the default expectation for .dlls is to be in {Project Root}/binaries/{platform} for windows; if you have it in the engine binaries this will still work, but that approach is less flexible IMO. If you’re binding for the mac platform it expects the .dylib at Plugins/{Plugin Name}/Binaries/Mac folder. I’m unsure of linux preferred location but I imagine it would be similar to the mac setup.

If you want an example, browse the source of the leap motion plugin you can find out how the dlls and the .libs are set up to load for either platform. In particular check out the build.cs where libs are loaded and this forum post where I talk about how mac expects a slightly different setup.

Do note that this is one approach and may not necessarily reflect best practices.

Hi getnamo,

i made some change in myforked version of the Joystickplugin. It is now working with SDL2 Inputsystem.
May have look. Maingoal was to get it working for my lab projects.

t.

Its great that you got it working, though I haven’t had the chance to test it with a joystick yet. Have you tried this version across different platforms? Does hot-plugging still work?

Nice work! Going with SDL sounds like the right move. There are still some features missing or incomplete in this version, like hot-plugging and multiple joysticks, but it looks mostly like a matter of adapting more of the old code.

I have to ask though, is there a reason why you changed the directory structure? If the source files don’t lie under the Source/ directory UE4 won’t find and build them for me at least. And, if you copy files instead of editing/moving them it’s hard to see exactly what is changed in the diffs.

A comment about the input mapping. I’m not sure only creating the inputs that exists on the Joysticks currently plugged in is the way to go. Possible inputs should probably “exist” so they can be mapped even if the joystick isn’t currently plugged in. Also, now “Device 0 Button 0” is a different input than “Device 1 Button 0” while for example the built in “Gamepad Face Button Left” is the same input even with multiple gamepads - but mapped to different players. There are cases when one player uses multiple joysticks (such as using a HOTAS) but maybe it should be a special case?

Are you interested in working more on this, even if it is working well enough for your lab projects now?

Indeed, it is. Without your work i couldn´t do my hacks.

Hmm, i put the files into my fork of UE4 in the plugins directory and it works fine. I try also put it into the plugins directory of some game projects with different UE4 versions and seems to run… IF i put the SDL2.dll in die binary directory of the plugins. Also compiled the SDL2 sources myself. Other ways i couldn´t get running.

Hmm, some of this points i play around with, but i didn´t found a solution wich works very well or stable. There are branches in my repo for. Ich changed many names to reflect a more abstract model of joysticks, gamepads etc.

I experiment with generating a one to one mapping of axis and buttons etc. So no more Device 0 Button 0 etc. Now it become to Button0_SaitekX52Pro… etc. this names where unique for each device. If the device is plugged on startup, no hotpluggin.

Multiple devices should work with this. I think one problem is that the InputMapping of UE4 takes over the device 0 each time.

HotpluggIn could work if i or someone else solve the regenerating problem of buttons, axis etc. - This is not a function i must have.

t.

Yeah, plugin files should be in the plugins directory. I’m talking about the source code files belonging to the plugin.
You have put them in /Plugins/JoystickPlugin/Public/ and /Plugins/JoystickPlugin/Private/
While the old files are still in /Plugins/JoystickPlugin/Source/JoystickPlugin/Public/ and /Plugins/JoystickPlugin/Source/JoystickPlugin/Private/ (which really confused me at first, because these files are the ones that are built for me)
If you look at plugins included in the engine like https://github.com/EpicGames/UnrealEngine/tree/release/Engine/Plugins/ScriptPlugin you see that a <PluginName>/Source/<ModuleName> directory structure is always used for the source code files.

I’m not currently using a full fork of the engine, I make a simple wrapper code project and put the plugin source code in the /Plugins directory. The build system then builds the plugin along with the project. Maybe the build works differently when building the whole engine, but don’t you think using the same directory structure as all other plugins is a good idea?

Maybe it’s just a matter of how you copied the files between your engine fork and the plugin git repo?

That sounds quite nice actually! This could even be specialized for certain joysticks, to get nice names for the buttons, like “Saitek X55 Switch 1”.

The issue I’m worried about is that FKey:s are used kind of like constants in many places:

InvalidKey.png

I can only create this event when that device is plugged in, and when it’s not I get a warning.

But this isn’t how it should be done anyway - when bound to an action/axis mapping there don’t seem to be any warnings about missing keys.
So I think you have convinced me, this seems like the best way. :slight_smile:

Now I’m just thinking about how to handle multiple devices of the same type in the best way… maybe default to making all devices control player 1, and make a function for assigning a device to another player? That should work well both for a HOTAS with two joysticks, and for split screen multiplayer.

I’ll try to help making hot plug work again if your not planning to do it yourself.

Hi,

update to this thread. Thanks the great work from samiljan the code is now much better and polished. The hotplug function seems to work.

A pitfall is that you have to start the game least once - til you get the joystick(s) appearing in die binding tool of the editor. We have to to a better init of the plugin.

I work successful with at the same time with an xbox360 controller and saitek x52 pro at the same time. My Microsoft Force Wheel2 only works with event handling in blueprints directly. I will work on this.
Client-/Server as we did it seems to work.

Binding:

Blueprint:

Hope the GitHub - tsky1971/UEJoystickPlugin: Unofficial Joystick Plugin for the Unreal Engine has much fewer issues.

t.

Just wanted to say that you guys are doing great work, keep it up :slight_smile:

Regarding input mapping, consider emitting two events for each action. One for the specific hardware and one which has a generic mapping to joysticks. This would allow default profiles to have basic functionality (and eliminate the need to have the plugin launch once before you can map it) while still allowing you to have specific hardware binding if you need it.

At some point we should find a way to have dynamic action rebinding such as Rama’s Rebindable Key System, but I wonder if it belongs in this plugin as extra content or as another general plugin?

Oh, there is nothing actually hindering adding all connected joystick buttons when the plugin is loaded, instead of when the first frame is run. I just accidentally removed that, sorry!

Wouldn’t emitting two events for one input change be bad for any dynamic action rebinding? The one bound would be whichever was emitted first first or last.
But it would be great if basic joystick support was really easy to add, and only more advanced joysticks needed configuration or dynamic rebinding!

I’ve tested some rebinding using the rebinding widget from Unreal Tournament. It’s quite simple and has no dependencies on Unreal Tournament: https://github.com/EpicGames/UnrealTournament/blob/28443da69ff209d67204a9a3b1c826c9e883bece/UnrealTournament/Source/UnrealTournament/Private/Slate/SKeyBind.h
I’ll try how Rama’s one works with the plugin!

Thanks for the great input! :slight_smile:

Okay, I made another big refactoring… Sorry :slight_smile:

So, I searched around in the UE4 source and found that there is a built in way to add custom input devices in plugins - the IInputDeviceModule. If the plugin inherits that interface the various F{platform}Application-classes will find it and call it every frame. This means no more JoystickPluginActor, simply enable the plugin and it will generate input events! It seems to work great for me. Have you tried using it for any of your other plugins, getnamo?

Then I figured JoystickPluginComponent isn’t really needed for blueprint events anymore either, so it’s gone too. Inherit the interface like before, but call “Register for Joystick Events” instead, like this:

Finally I added a way to map a device to another player - it works great for split screen games for example.

All in all it means both simpler initial setup and code structure.

I put it here for now: https://github.com/samiljan/UEJoystickPlugin/tree/IInputDeviceModule

Thats ok. :wink: The changes are really good. I believe now this your project. :slight_smile: Perhaps epic put it to the defaults…

For me the most things work great, except the autonaming convention of devices. The old convention takes care of editing the mapping because of the size of the dropdown menu.

Old style lets see what´s the actual mapping is. In this (rarely i hope) case the name is cutted and only the tooltip show the hole name.

If you want to edit the mapping this happens:

tooltipnotshown.png

So may be we change in the engine the tooltip to show the actual name of the device it hovers over ? Or change the size of the editfields to the max name length ?

Thats only polishing things…

What matters is: the plugins now works fine with SDL2. I try my ancient old usb-joywarrior-adapter for my rc-controller and it works. :wink:

t.

I found a way to hack the editor from the plugin and make the fields wider. It’s ugly but it seems to work…

wide input mapping.PNG

https://github.com/samiljan/UEJoystickPlugin/tree/IInputDeviceModule

Great change. This works fine.

Before someone complains : Did you recompile the code ? In the file "InputSettingsCustomization.cpp " in line 68 and 185 : I had to add toString(), because of complaints of the compiler.


error C2664: 'FDetailWidgetRow &IDetailChildrenBuilder::AddChildContent(const FString &)' : cannot convert argument 1 from 'FText' to 'const FString &'
1>          Reason: cannot convert from 'FText' to 'const FString'
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Ohh, it seems this was recently changed in UE - I only tried this with UE 4.7 Preview.
That’s the danger when poking around in internal code I guess, it’s much less stable. Maybe there is a workaround that compiles both on 4.6 and 4.7?

If we had the Engine Source available then we could use:

#if ENGINE_MINOR_VERSION<7
StructBuilder.AddChildContent(LOCTEXT(“KeySearchStr”, “Key”))
#else
StructBuilder.AddChildContent(LOCTEXT(“KeySearchStr”, “Key”).ToString())
#endif

=8-O

But it´s an “workaround” that seems to work -> only with engine source.

I made a simple workaround for now - a wrapper class that calls ToString if needed

tsky, a suggestion: if you add my repo as a git remote and merge into your branch the commit history won’t get lost.
Something like this:



// Only once
git remote add samiljan https://github.com/samiljan/UEJoystickPlugin.git

// Fetch and merge new commits into the current branch
git fetch samiljan
git merge samiljan/IInputDeviceModule


ok this solution works and ist much nicer as the #if style.

repos: I normally not use github, because i am running my own servers (no remotes to github etc.). Now i change my working style and use remotes on github too. :wink:

I’m no git expert, I just learned how merge from another remote the other day and wanted to share :slight_smile:
All these branches and forks of this plugin has forced me to learn a lot, it’s great! And you have to admit github is great for sharing code!