Input is overridden by navigation input in Common UI. How to override?

Hey all,

I am trying to retrieve an input action that is binded on an input that is normally also used for navigation: E.g. thumbstick left left / left right, gamepad left/right etc.

When I change the input to anything else e.g. face button top, the button is being triggered (clicked). But when I assign it to something that is used for navigation, it gets consumed and does not trigger the bound button.

I did find a workaround. For anyone that is searching for it, basically it is forcing the listen to the input and execute a custom event in the widget itself.

However, I would like to not use this workaround for cleanness. If anyone has an idea, please feel free to reach out.

Thank you in advance and with kind regards,

Eric

1 Like

Hey, as I’m facing the same problem, I wanted to thank you for your workaround.

And while I was implementing it, I also found another way:
In my widget “container” (for me it’s an horizontal box), I saw you can bind custom functions to respond to navigation input:

image

I’m not sure that’s what you are looking for, or if it’s “CommonUI-friendly”, but just wanted to mention it.

Thanks! Will try if this solves the automatic listen. For now my workaround seems very stable. I have found multiple of these things in Common UI. Probably will do a tutorial series on it.

The way I managed to work around this issue is to create a subclass of FNavigationConfig and to set it using FSlateApplication::Get().SetNavigationConfig(NavigationConfig);.
In my subclass, I overrode some methods such as virtual EUINavigation GetNavigationDirectionFromKey(const FKeyEvent& InKeyEvent) const override; that returns EUINavigation::Invalid when I disabled navigation.
You can also define your “mappings” for instance, the default is:

FNavigationConfig::FNavigationConfig()
	: bTabNavigation(true)
	, bKeyNavigation(true)
	, bAnalogNavigation(true)
	, bIgnoreModifiersForNavigationActions(true)
	, AnalogNavigationHorizontalThreshold(0.50f)
	, AnalogNavigationVerticalThreshold(0.50f)
{
	AnalogHorizontalKey = EKeys::Gamepad_LeftX;
	AnalogVerticalKey = EKeys::Gamepad_LeftY;

	KeyEventRules.Emplace(EKeys::Left, EUINavigation::Left);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Left, EUINavigation::Left);

	KeyEventRules.Emplace(EKeys::Right, EUINavigation::Right);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Right, EUINavigation::Right);

	KeyEventRules.Emplace(EKeys::Up, EUINavigation::Up);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Up, EUINavigation::Up);

	KeyEventRules.Emplace(EKeys::Down, EUINavigation::Down);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Down, EUINavigation::Down);

	// By default, enter, space, and gamepad accept are all counted as accept
	KeyActionRules.Emplace(EKeys::Enter, EUINavigationAction::Accept);
	KeyActionRules.Emplace(EKeys::SpaceBar, EUINavigationAction::Accept);
	KeyActionRules.Emplace(EKeys::Virtual_Accept, EUINavigationAction::Accept);

	// By default, escape and gamepad back count as leaving current scope
	KeyActionRules.Emplace(EKeys::Escape, EUINavigationAction::Back);
	KeyActionRules.Emplace(EKeys::Virtual_Back, EUINavigationAction::Back);
}

But the engine also offers an alternate nav config with a subclass defining its own rules (and a good place to learn more about the Navigation config):

FTwinStickNavigationConfig::FTwinStickNavigationConfig()
{
	bTabNavigation = false;

	KeyEventRules =
	{
		{EKeys::Gamepad_DPad_Left, EUINavigation::Left},
		{EKeys::Gamepad_DPad_Right, EUINavigation::Right},
		{EKeys::Gamepad_DPad_Up, EUINavigation::Up},
		{EKeys::Gamepad_DPad_Down, EUINavigation::Down}
	};
}

You can simply rebind the navigation input in this way, without creating new subclasses. Don’t forget to connect the Slate module and include Slate.h.

	TSharedRef<FNavigationConfig> InNavigationConfig = FSlateApplication::Get().GetNavigationConfig();

	InNavigationConfig.Get().AnalogHorizontalKey = EKeys::Gamepad_RightX;
	InNavigationConfig.Get().AnalogVerticalKey = EKeys::Gamepad_RightY;

	FSlateApplication::Get().SetNavigationConfig(InNavigationConfig);
1 Like