OTHGMars Posted March 20, 2018 Share Posted March 20, 2018 (edited) This is a wip branch that adds support for the SDL_Joystick and SDL_GameController sub-systems to T3D: https://github.com/OTHGMars/Torque3D/tree/SDL_Joy_wipHopefully with some code-reviews/community input/testing this can be improved and a clean PR made so T3D will have device independent joystick and gamepad support.TestingTo encourage testing, there's a testing module that creates an event viewer gui so you can view events that your devices generate in real-time (it's more fun than stepping through the event loop in the debugger). It also has a settings window so you can see the effect the prefs have on how devices are opened if they are connected or disconnected. After building the engine and installing BaseGame, copy the inputTest directory from Templates/Modules to your game/data directory. It will add a button for the event viewer to the main menu. Please throw any gaming-type input device you have at it and post your results. I do not have any devices with a trackball, so those events are completely untested.The DetailsThe input model under SDL is different than the existing DInputDevice platform code. Under SDL all input devices other than keyboard/mouse are considered Joysticks. Game Controllers are a subset of Joysticks. The advantage to using Game Controllers is the SDL database of controller mappings. Recognized gamepad devices can be mapped to the xbox input scheme so a single set of ActionMap defaults can be identical buttons on different devices. Additional mappings can be loaded from script or file. More info at https://wiki.libsdl.org/SDL_GameControllerAddMappingsFromFileThere's a new global, $pref::Input::sdlControllerEnabled. If true, any device that SDL recognizes as a Game Controller will be automatically opened as a controller and these events will be used: https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platform/input/event.cpp#L392-L430.The existing global $pref::Input::JoystickEnabled is still used. If true, any device that cannot be recognized as a Game Controller (or all devices if pref::Input::sdlControllerEnabled is false) will be automatically opened as a Joystick and these events will be used: https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platform/input/event.cpp#L309-L390.If both globals are false, no joystick devices will be opened. There is a script interface for opening/closing and getting device details that closely mirrors the SDL_Joystick and SDL_GameController function sets if you do decide to take manual control of opening/closing devices from script.New events were added for trackballs and the guide button on gamepads.There are 2 new script callbacks that fire anytime a device is connected or disconnected, onSDLDeviceConnected() and onSDLDeviceDisconneceted(). The connected callback is called before the device is opened by the InputManager so you can modify default behavior if you need to.Unresolved QuestionsIs it possible to use the DECLARE_CALLBACK IMPLEMENT_CALLBACK macros with a class that's not a CONOBJECT? If so, that would be cleaner and easier to document than the current Con::executef() method, but I couldn't figure out how to do it.Edit: I used the IMPLEMENT_GLOBAL_CALLBACK macro and was able to implement the connect/disconnect callbacks.I left this enumeration commented out https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platformSDL/sdlInputManager.cpp#L30-L42. It worked as the return value here https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platformSDL/sdlInputManager.cpp#L990, but I could not find the correct way to get the string from the value here https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platformSDL/sdlInputManager.cpp#L1044. Lookup is complicated by the fact that the enumeration contains a negative value. So, I went with a simple static lookup function https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platformSDL/sdlInputManager.cpp#L81. I'm looking for suggestions for a better way.Edit: castConsoleTypeToString() is the function I was looking for. This if block, https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/windowManager/sdl/sdlWindowMgr.cpp#L262-L268 could be where it is now, or it could be in the default branch of the switch statement just below it. Is there a preference? Is one better?Edit: Left as is.As is sometimes the case with T3D, you go to start something and realize something else needs fixed first. I liked the LOG_INPUT define in the old platform layer, so I defined it when starting on this, but the engine wouldn't build under windows. I 'fixed' that as the first commit. I wouldn't use it anymore since the event monitor gives as much information. But...Since it's in the code, I really should verify it works under Linux or take it back out. I don't have a Linux test environment atm, so if anyone could help out with that, it would be greatly appreciated.Edit: Removed from the code.Because of the way they're generalized, these functions https://github.com/GarageGames/Torque3D/blob/development/Engine/source/app/game.cpp#L70-L88 will activate and deactivate the sdl input manager...I'm not sure if duplicates should be made with general names or if it should left as is? If the legacy platform code is going to be depreciated at 4.0 in favor of all sdl, the activation/deactivation could be cleaned up and some functions that only exist to match the old structure could be removed. Edited May 13, 2018 by OTHGMars Quote Link to comment Share on other sites More sharing options...
irei1as Posted March 22, 2018 Share Posted March 22, 2018 Thanks a lot for the effort. It works well for my Trust compact gamepad gtx24. It detects it as joystick.All the buttons work as normal except, the horizontal of the right stick is detected as both "zaxis" and "rxaxis".But that may be because some faulty drivers I tried to install for an old controller so, what would be the ingame behaviour of a key that throws simultaneously two inputs?As side note, the keyboard is detected as the default English layout instead of my Spanish one, so my ñ key is detected as ; and < between left shift and z isn't recognized (throws a "" as key name).http://ascii-table.com/img/keyboard-071.pngBut, well, Torque hasn't supported non-English layouts as long as I recall. So I don't think it's very important.If anything I guess the azerty or devorak users have it worse.Ah, F1 doesn't work for me to show the config menu (console throws: pushDialog(): Invalid control: HelpDlg).But I can get it to work usingCanvas.pushDialog(JoystickSettingsDlg) Quote Link to comment Share on other sites More sharing options...
OTHGMars Posted March 22, 2018 Author Share Posted March 22, 2018 @irei1as Thanks for testing and giving feedback!If the driver is actually generating 2 events and the ActionMap has 2 bindings, both would get called.I forgot that F1 has a GlobalActionMap bind in the Full template. I should have picked a different key for that. Anything with a bind in the GlobalActionMap gets pulled out of the event loop before it gets to the gui. Glad you found the work-around.I've never looked at sdl keyboard layout handling, but I made a note to check it out the next time I'm in the docs. Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 24, 2018 Share Posted March 24, 2018 Hey, thanks @OTHGMars, it's sure nice having a community that happens to be working on exactly what I need! 8-) I took a chance and hacked your changes straight into my main build (not all the way up to date with head by any stretch) and it seemed to work out fine. With my Logitech Extreme3D Pro I get all the buttons working as expected. I had some trouble between the hat and the slider though, where rxaxis (hat horizontal) works but ryaxis (hat vertical) doesn't seem to give me anything, and the slider (throttle) seems to think it is the ryaxis. Results varied, not sure what all was up there.I haven't tested the main joystick axes yet.EDIT: for the main axes, X and Y seemed to work but I'm not getting anything for Z (twist) yet. Quote Link to comment Share on other sites More sharing options...
OTHGMars Posted March 24, 2018 Author Share Posted March 24, 2018 @chriscalef Thanks for sharing your results. Does that Joystick report as a 4 or 6 axes in the test module (or sdlJoystickNumAxes(0) in the console)? If it's reporting as a 4 axis, I'd try commenting out these two lines and checking the axis events again. https://github.com/OTHGMars/Torque3D/blob/SDL_Joy_wip/Engine/source/platformSDL/sdlInputManager.cpp#L193-L194 Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 25, 2018 Share Posted March 25, 2018 It reported as 4 axis, and your fix seems to have gotten the main stick reporting accurately, however now my slider (throttle) reports as RXaxis and I don't get anything from the hat, which I would expect to be RX and RY.Also, I feel like I already know this, but how does one pull an actual value out of these controls as opposed to just getting a callback? Having a minor memory malfunction... Quote Link to comment Share on other sites More sharing options...
OTHGMars Posted March 26, 2018 Author Share Posted March 26, 2018 @chriscalef This is probably the function that you're remembering: https://github.com/GarageGames/Torque3D/blob/development/Engine/source/platformWin32/winDirectInput.cpp#L852. SDL does have equivalent commands for polling individual device states but they are not exposed as console functions in this branch. I'll be sure to get those added before a PR is made.I would expect the hat to generate dpad events though, https://github.com/GarageGames/Torque3D/blob/development/Engine/source/platform/input/event.cpp#L374-L377. Were you able to run the input monitor to see if the hat was generating any events? Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 26, 2018 Share Posted March 26, 2018 Ah sorry, I was in a mad rush so once I added your engine code and realized I was getting button callbacks, I didn't bother to install your scripts. :oops: Now I'm all out of weekend, but I'll try to get back to that tonight.Meanwhile, though, I do know that the hat does something, because before I fixed the 4 axis thing I was getting reliable RXaxis returns from the horizontal axis. However, the vertical axis and the slider got mixed up with each other. Quote Link to comment Share on other sites More sharing options...
OTHGMars Posted May 13, 2018 Author Share Posted May 13, 2018 This code has been updated for SDL 2.0.8, cleaned up and PR'd as #2256. The new branch is: https://github.com/OTHGMars/Torque3D/tree/SDL_Joystick. The original post has been updated with the answers to a couple of the questions I had there. The input test module (useful for discovering device capabilities and monitoring input events) has also been updated and is now available here: https://github.com/OTHGMars/Torque3D/tree/InputMonitor. Quote Link to comment Share on other sites More sharing options...
OTHGMars Posted July 19, 2018 Author Share Posted July 19, 2018 The joystick branch now includes a keyboard event refactor that eliminates keycode and modifier conversions. This opens the possibility of supporting ANSI and ISO keyboards in any layout that SDL recognizes. Help is needed in order to get this properly tested and working in time for 4.0. If you use a non US keyboard layout or have any type of gaming input device, please see testing below and post your results.TestingTo test, pull in the joystick branch and test module (install BaseGame with one of the Gameplay and inputTest modules). It will allow you to see events that would otherwise require you to set binds & breakpoints or use the remap gui. Test every standard key on your keyboard. Any keys bound in the global action map like the Grave Accent on US layout will execute that function instead of appearing in the input monitor. You can still see an event generated by using a modifier key with them. If any key does not produce an event name in the monitor, open the console and there will be an error message ("ActionMap::getKeyString: no string for action %d") in the console. Please post the number printed, the key pressed, your layout and OS in this thread. The action number will correspond to this enumeration. No, we don't support every scancode in the USB standard so there's no bind for the mute function etc. of modern keyboards. If you find any key that you think should be added, please bring it up. The text input of all printable characters can be tested in the console gui.When initially testing a joystick device, open the settings window (f2 from the monitor) and turn the deadzone up past half-way. That makes it easier to verify the individual axis events in the monitor.New Joystick OptionsPOV Hat data is provided as a 4 bit mask value and interpreted to produce the standard upov, dpov, lpov and rpov events. Set pref::Input::JoystickPOVMask true to receive a povmask event with the current hat state every time it changes. This defaults to false so standard behavior is consistent with the previous direct input event handling.A joystick device that only has 4 axes will always report axes 0-3. In torque mapping this becomes xaxis, yaxis, zaxis and rxaxis. There's an option, pref::Input::JoystickSplitAxesLR, that if true will map axes 2/3 to rxaxis/ryaxis instead of zaxis/rxaxis. This option only affects 4 axis joysticks.Checkboxes have been added to the settings gui in the test module so you can see the effects of these settings without needing to type them out in the console.My Test ResultsUS keyboard layout, all keys and modifier combinations produced the correct bindable event. The only other devices I have are a Logitech RumblePad 2 (c2007) and an Xbox One controller. SDL has built-in controller mapping for the logitech so I was able to open both as joystick or gamepad. Both devices produced the correct events for all inputs. The Logitech was not detected as a haptic device (it is) and the wired/battery status returned unknown. Every feature of the Xbox controller was detected correctly. Quote Link to comment Share on other sites More sharing options...
Steve_Yorkshire Posted July 20, 2018 Share Posted July 20, 2018 Just had a quick play with SDL_Joystick branch (minus testing branch). UK keyboard, X-Box Controller.Xbox Gamepad:Y axis on both thumbsticks are reversed (forwards=back, up=down). X axis works fine. Buttons work fine.Keyboard:Console is under Esc (which is not tilde on UK keyboard) but that is where everyone wants it. All other keys work as expected. Quote Link to comment Share on other sites More sharing options...
Steve_Yorkshire Posted July 20, 2018 Share Posted July 20, 2018 Had a play with the input monitor and moving the both left/right thumbsticks up/forward do give negative values (eg: -0.99999) whilst down/back is positive (eg: 1.0) so I reckon this need reversing :mrgreen: Quote Link to comment Share on other sites More sharing options...
Steve_Yorkshire Posted July 20, 2018 Share Posted July 20, 2018 Swapping the +/- around in default.bind.cs does the trick function gamePadMoveY( %val ) { if(%val > 0) { $mvForwardAction = -%val * $movementSpeed;//swapped to negative for sdl $mvBackwardAction = 0; } else { $mvForwardAction = 0; $mvBackwardAction = %val * $movementSpeed;//swapped to positive for sdl } } //... function gamepadPitch(%val) { %pitchAdj = getGamepadAdjustAmount(%val); if(ServerConnection.isControlObjectRotDampedCamera()) { // Clamp and scale %pitchAdj = mClamp(%pitchAdj, -m2Pi()+0.01, m2Pi()-0.01); %pitchAdj *= 0.5; } if(%pitchAdj > 0) { $mvPitchDownSpeed = -%pitchAdj;//swapped to negative for sdl $mvPitchUpSpeed = 0; } else { $mvPitchDownSpeed = 0; $mvPitchUpSpeed = %pitchAdj;//swap to positive for sdl } } And then all is right with the world once more 8-) Quote Link to comment Share on other sites More sharing options...
Steve_Yorkshire Posted July 20, 2018 Share Posted July 20, 2018 And a prettier way of doing it ... function gamePadMoveY( %val ) { if(%val > 0) { $mvForwardAction = 0; $mvBackwardAction = %val * $movementSpeed; } else { $mvForwardAction = -%val * $movementSpeed; $mvBackwardAction = 0; } } //... function gamepadPitch(%val) { %pitchAdj = getGamepadAdjustAmount(%val); if(ServerConnection.isControlObjectRotDampedCamera()) { // Clamp and scale %pitchAdj = mClamp(%pitchAdj, -m2Pi()+0.01, m2Pi()-0.01); %pitchAdj *= 0.5; } if(%pitchAdj > 0) { $mvPitchDownSpeed = 0; $mvPitchUpSpeed = %pitchAdj;//swap to positive for sdl } else { $mvPitchDownSpeed = -%pitchAdj;//swapped to negative for sdl $mvPitchUpSpeed = 0; } } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.