Hello,
I am looking at trying to implement Gamepad/Keyboard input for widget navigation and interaction. I have been investigating the FCommonAnalogCursor as an option, but notice this is only available for Gamepad and does not take into account keyboard input. I was wondering on what the intended way for implementing navigating widgets and using them (like clicking a button) is for the Keyboard input?
Furthermore, is the Analog Widget approach still the preferred way for Gamepad input in the first place?
Any information on this would be useful,
Cheers
Hi,
There’s some level of navigation support built into Slate by default; arrow keys and directional pad for navigation, enter/space/bottom face button for confirm, and escape/back button for back. You can customize these bindings by writing your own class that extends FNavigationConfig and registering it via FSlateApplication::SetNavigationConfig. This should handle most basic navigation, and it can be helpful to temporarily set Render Focus Rule to Always in your project settings so you can see a visual for which widget is focused.
In CommonUI, we introduced the CommonAnalogCursor to solve the problem of visualizing focus when using gamepad controls. Widgets only have a hover style and not an explicit focus style, so we solved this by moving an invisible cursor over the focused widget to trigger it’s hover style (and clicking it when the face button is pressed). This virtual click supersedes the standard Slate navigation controls, but only if you’re using CommonUI and have the cursor enabled (Link Cursor to Gamepad Focus in your project settings).
So to summarize, keyboard navigation will already work out of the box, but you’ll be missing the triggering of hover visuals that you get from CommonAnalogCursor for gamepad navigation. There’s a bit of info on why we made that decision on this docs page, but essentially when navigating via keyboard we operate under the assumption that you’re also using a mouse and don’t want scenarios where both have an active “hovered” widget since that would be pretty confusing.
If you plan to hide the mouse cursor and use keyboard navigation similar to how you’d navigate with a gamepad, you’ll need to do some manual style flipping. Depending on how complex your interface is, it may suffice to write a custom button class that switches style on focus and let the built-in navigation trigger those focus events to tell your button to switch styles. You could also experiment with manually moving the CommonAnalogCursor , either by modifying the cursor class to also handle keyboard input or by extending CommonUIActionRouterBase to move it when needed.
Best,
Cody
Hi,
Fair point, the “navigation” accept action is handled by certain widgets out of the box (SButton, SCheckBox, etc.) but if you’re working within CommonUI then you’ll likely want to set up accept/back input actions and bind those actions to widgets where appropriate. It may make sense to disable the CommonAnalogCursor entirely if you want robust navigation support for both keyboard and gamepad, as you’ll need to manually implement a lot of what it does (hover styles and input handling) yourself.
Best,
Cody
Thanks for the reply!
It seems the keyboard navigation is fine as you mentioned, although the confirm being driven from space/enter is causing a bit of confusion.
The only cases I could see that working was from either SButton::OnKeyUp handling it, or in the case of UCommonButtonBase there is TriggeringInputAction that I could add an action to (Which I had tried out by adding an input on the Lyra project to test getting keyboard input working, as it didn’t seem to by default).
I was curious on what would be expected method in the cases where we want to have the same “confirm something with space/enter” on a widget that isn’t derived from a button class, but instead just uses the UCommonActivatableWidget or UCommonUserWidget classes. Would you expect it to be done through bindings, or through the NativeOnKeyDown or any other method?
Cheers