Set Input Mode "Game & UI" with Common UI plugin

Hello,
I’m currently using common ui for my menus and everything works great in terms of menu navigation . I would like to reroute some controller input to the game to recreate a “Dark Soul menu type”. I tried the “Set Input Mode : Game & UI” . But all the inputs events seems to be trapped by the CommonUI layer. Do I missed to do a specific config ?

Thanks in advance

1 Like

I’ve run into this as well. I rewrote some code that used to work and now no longer works.

Like pressing the i key to toggle the inventory screen. Game input now only works if I hold down right click.

I found that in the C++, there’s also something to do with UIInputConfigs in common UI.

This code thinks the UI is handling all keyboard events.
https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Plugins/Experimental/CommonUI/Source/CommonUI/Private/CommonGameViewportClient.cpp#L65

Ultimately this is because the CommonUIActionRouterBase returns BlockGameInput here.
https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Plugins/Experimental/CommonUI/Source/CommonUI/Private/Input/CommonUIActionRouterBase.cpp#L403

The UIInputConfig is somehow set to Menu instead of All. I saw that me calling Set game input mode to UI and Game doesn’t affect this. I’d assume this is a bug.

2 Likes

After some more digging I got the keys to work by setting my common activateable widget’s Action Domain Override with a data asset that has Input Mode set to “All”.

I’m not yet sure if this is the best way but it should trigger this widget to correctly allow keys to route to the game instead of being blocked by being in Menu mode. That seems like the default.

I saw in my logs something like this which happens if you do nothing:
[2023.01.16-07.51.23:419][938]LogUIActionRouter: Display: Applying input config for leaf-most node [UMG_UI_AGHUDWidget_C_0]

[2023.01.16-07.51.23:419][938]LogUIActionRouter: Display: UIInputConfig being changed. bForceRefresh: 1

[2023.01.16-07.51.23:419][938]LogUIActionRouter: Display: InputMode: Previous (None), New (ECommonInputMode::Menu)

More:

Seems like CommonActivateableWidget also has a method:

This by default returns the default FUIInputConfig with Menu as the setting.

https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Plugins/Experimental/CommonUI/Source/CommonUI/Private/CommonActivatableWidget.cpp#L69

Maybe it’s not necessarily a bug but this is completely undocumented. It seems like each activateable widget can set its own input config, and the leafmost widget decides this.

A lot of this isn’t even modifiable with blueprint since these are functions deep in C++.
I would think the default should actually be “All” instead of “Menu” so it just works with whatever the player controller input mode is set to.

2 Likes

I am basically stuck with the same challenge right now. I want to have my in game UI (buttons where the user can select a building) also made with commonUI, but I am stuck that it swallows all input even for camera movement …

I tried giving the player controller game and ui input method on my root widget. Nothing works …

Shouldn’t the viewport client cascade inputs through?
I mean the second code @illYay shared should do exactly that right? But digging into ‘CanProcessNormalGameInput’ I have no idea to satisfy the bool expression which checks that the widget has captured the cursor.

Does anyone know how to achieve this?

Because looking at the first code you shared if it is unhandled by the CommonGameViewportClient it passes the input on to the parent method which should then just pass it on as normal right?

Regarding the original post from @Kranfucius, at the end we achieved what we wanted by creating a new child class from UCommonActivatableWidget.
This new child class called UCommonActivatableGameInputAllowedWidget overrrides the GetDesiredInputConfig method setting the input mode to All.

Since CommonUI goes through the widgets hierarchy looking for someone that define a UIInputConfig (thanks to the Optional C++ container), we just need to make our Widget root class specify the new child class.

4 Likes

Thanks @Jamil for your idea to subclass the activatable widget from commonUI. After I read your post I looked into lyra and used their approach to have it configurable in the editor UI.

That kind of works, but due to some shenanigans under the hood the mouse cursor is hidden for me. I need the cursor visible though, because I want to use commonUI as the ingame UI where the user can click and select their building. Well that works with the cursor visible, if I am not capturing it, but then I need to basically double tap all my non UI commands to take effect: what was before a left click is now a double left click.
Haven’t dug into it why this happens.

I don’t know its weird. For example if I chose ‘capture’ everything works fine, except I don’t see the cursor since it is hard hidden by a console variable …

That sounds like what I’m planning to do as well. It makes me kindof question if this is the best method though. If they exposed that domain override to blueprint and not this other function, maybe we use the domain override after all?

@conscienc3 @illYay I use a sometimes-visible mouse in my Lyra game.

In UE/Lyra 5.1 it requires a custom engine hack to get a visible mouse to work well with CommonUI.

In UE/Lyra 5.2 that is supposed to be fixed so it will no longer require a custom engine.

TLDR CommonUI must be used to control the input mode. You should hook into CommonUI to make whatever changes you want when the input mode changes. (Like showing or hiding the mouse).

I tried to document this stuff here:

1 Like

Thanks @xi57.

How have you achieved to display the mouse in 5.1?

I continued today and didn’t really come far: I can show the mouse now as I wanted to. A bit hacky but the current implementation leaves me no choice. I had to execute the commandline command in the blueprint to forcefully show the cursor.

Capture

Like this in the BeginPlay of my GameMode.

Not pretty but this works.

To my double click issue: I haven’t really figured out yet why the engine and commonUI for that matter sometimes lets the input through and sometimes not. I have trouble to debug it since any breakpoint in that chain is triggered by my first click into the Editor Window … so that is kinda cumbersome.

I mean the thing is CommonUI was designed for Menus in Fortnite and was also used in Lyra for this usecase. I feel like fighting against a rigid framework, which intent is currently not to be used in game.
I would love to have the keys automatically shown and the select and hover state and stuff, but maybe I end up scratching CommonUI for now and build my own crappy UI base component … in the end its just a button … right? :fearful:

1 Like

In Unreal Engine, you can use the Set Input Mode : Game Only function to capture controller inputs for the game, rather than for the UI. Additionally, you can use the Set Input Mode : UI Only function to capture inputs only for the UI, or Set Input Mode : Game And UI to capture inputs for both the game and the UI simultaneously. Keep in mind that you need to set the input mode in the appropriate event, such as when the menu is opened and closed.

If you need a visible cursor, get the Player controller and set the show cursor to true.

Technically; from what I can read, these should work for the CommonUI plugin.

With Common UI, you probably don’t want to be explicitly setting the input mode.

Instead, you should use Common UI itself to manage the input mode.

This plugin is still experimental and as of 5.1 it requires a custom engine to do much to change its default behavior.

I understand updates are in place for 5.2 to make it easier to work with. Until then unless you are comfortable with C++ and custom engines, in 5.1 the control over how the mouse is used is limited.

Are you talking about how the mouse isn’t visible if controller input is enabled? I don’t seem to have cursor issues myself. If I set the player controller to show the mouse, it shows. As soon as a controller input is pressed the mouse disappears. Then when I move the mouse again it shows.

I did notice also the mouse might appear even when you just activate a widget and you have to manually call set input mode to game only and hide the cursor.

For example I modified the lyra loading screen code to let the user push a button to close the loading screen so they can read some story text. Activating the loading screen widget so they can push the button forces the cursor to show and to not have game inputs come through without me ever having called those functions myself. After pushing continue I have to call set input mode Game Only again. I’m still a bit confused because a lot of this isn’t documented yet and you figure it out while debugging.

I haven’t seen exactly how to make Common UI manage the input mode unless you mean having the input type returned as Menu, All, Game from common activatable widgets? It does technically seem like a better way.

I also noticed Action Domain related settings in the common UI input settings. This is completely undocumented but it seems like a lot of the input mode handling is done through this?
https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Plugins/Experimental/CommonUI/Source/CommonInput/Public/CommonInputSettings.h#L92

I also saw Lyra just has this under ULyraActivatableWidget. Why this isn’t just part of the base class, I’m not sure, but these are the exact options I was looking for in UCommonActivatableWidget. I guess this is the best way. No need to try to understand all the other stuff for now.

UENUM(BlueprintType)
enum class ELyraWidgetInputMode : uint8
{
	Default,
	GameAndMenu,
	Game,
	Menu
};

// An activatable widget that automatically drives the desired input config when activated
UCLASS(Abstract, Blueprintable)
class ULyraActivatableWidget : public UCommonActivatableWidget
{
	...
	
public:
	
	//~UCommonActivatableWidget interface
	virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override;
	//~End of UCommonActivatableWidget interface

...
	
protected:
	/** The desired input mode to use while this UI is activated, for example do you want key presses to still reach the game/player controller? */
	UPROPERTY(EditDefaultsOnly, Category = Input)
	ELyraWidgetInputMode InputConfig = ELyraWidgetInputMode::Default;

	/** The desired mouse behavior when the game gets input. */
	UPROPERTY(EditDefaultsOnly, Category = Input)
	EMouseCaptureMode GameMouseCaptureMode = EMouseCaptureMode::CapturePermanently;
};


TOptional<FUIInputConfig> ULyraActivatableWidget::GetDesiredInputConfig() const
{
	switch (InputConfig)
	{
	case ELyraWidgetInputMode::GameAndMenu:
		return FUIInputConfig(ECommonInputMode::All, GameMouseCaptureMode);
	case ELyraWidgetInputMode::Game:
		return FUIInputConfig(ECommonInputMode::Game, GameMouseCaptureMode);
	case ELyraWidgetInputMode::Menu:
		return FUIInputConfig(ECommonInputMode::Menu, EMouseCaptureMode::NoCapture);
	case ELyraWidgetInputMode::Default:
	default:
		return TOptional<FUIInputConfig>();
	}
}
1 Like

@illYay Yes what you wrote in your last post is what I also adopted. I am still left with the double click issue.

@EliasWick Not sure what you mean to be honest. I think illYay and I want to achieve the same’ish thing: Having CommonUI handle its input and what ever it can not handle pass through to the game. What you suggest would work if you are switching between a menu and the game with like in the content example. But if you have a ‘menu’ aka CommonUI elements on screen and want the user to interact with it and also at the same time let the user pan the camera and trigger actions in the player controller, this is what does not work right now.

@xi57 But as we pointed out earlier, that CommonUI at several places catches all inputs and blocks them without the snippet from Lyra (what Jamil and illYay mentioned). Can you be more specific? And keep in mind that we don’t use Lyra as a base.

I only use Common UI in the context of Lyra. I can’t speak to how it may be implemented in other contexts.

@illYay found applicable Lyra C++ code that makes Common UI work well. If you don’t use Lyra, you’ll have to duplicate this (and other similar related) code into your own code base and modify as needed.

@conscienc3 the double click issue can be fixed with a custom 5.1 engine hack and some C++ overrides in your project.

Ultimately the problem is in UCommonUIActionRouterBase::ApplyUIInputConfig. You need to make it protected virtual, and promote ActiveInputConfig to be protected as well.

Then you derive from UCommonUIActionRouterBase to your custom class, override ApplyUIInputConfig and make whatever input changes you want for your project.

Two clicks are consumed in your case probably because you are not capturing the mouse in your current input config. Thus the first click initiates the capture and the second is the first one your project sees.

You need to set the mouse to be captured including the initial mouse down to have every single click always go to your project. Something like this:

GameViewportClient->SetMouseCaptureMode(EMouseCaptureMode::CapturePermanently_IncludingInitialMouseDown);

In your project using Common UI, THIS is where you manage the input modes, capture modes, everything related to user input: your ApplyUIInputConfig override.

In 5.2 this won’t require a custom engine. In 5.1 it does, I listed the minimal required changes above.

Good luck! :+1:

I’m actually copying out a lot of Lyra code as a module and using it in my project already. It’s basically a modified version of LyraGame where I omit a huge chunk of unneeded things and copy over some classes with any modifications needed to make them work.

Alright :slight_smile: Nice! Thank you for your explanation.

I now ended up with a very wonky setup: Since I am reluctant to build my own button, which would do essentially the same as the common ui button I am using the common ui buttons now in my user ui, but without embedding it in a activatable widget. That somewhat helped since I am not constantly fighting against the action router. So when I need a menu I add it to the viewport and do my things there. Once everything is removed I also remove the activatable widget again which holds the menu. Your hint with the capture mode did then the trick. Since I now just set it to capture including initial mouse down once all menus are gone and it works as I expect it … well 'ish I must say.

The buttons do their button thing when I click them and when I click the corresponding key it also works, but under some circumstance the mouse cursor resets to the middle of the screen. I am ok with that for now. Once Unreal 5.2 is released I give that a look. For now I am quite hesitant to do engine changes. Already spend a ton of time on CommonUI and want to move on :slight_smile:

So in summary: I use CommonUI buttons in a vanilla UMG UserWidget for the ingame UI. Once I need a menu I add it to the viewport based on a CommonUIActivatableWidget. When the menu is not needed anymore I hard set the capture mode to EMouseCaptureMode::CapturePermanently_IncludingInitialMouseDown.

I still think that going with CommonUI is a generally good idea, since it takes care of so many cases you would end up implementing anyways in one way or another.

That’s part of the same issue - the default UE 5.1 UCommonUIActionRouterBase::ApplyUIInputConfig implementation, while it works for Fortnite and Lyra, doesn’t work well for other types of games. It must be overridden.

Basically any time any of the Common UI widgets change the UI state, this function gets run, which is then going to totally mess up your UI in a non-shooter type game. (Unless/until you override it and have it do the correct thing for your game).

Once 5.2 releases, this function (and the variable it needs to set) should be protected virtual, and so then you’ll be able to customize this stuff without having to build a custom engine.

I also noticed Common UI Buttons are actually a wrapper on top of regular buttons.
In fact I wrote my own interactable target that works slightly better than buttons do and handles drag drop operations more seamlessly. It works flawlessly with Common UI because under the hood Common UI Buttons are still using standard SButton and other Slate code without heavy changes.

All you really get from Common UI Buttons is the extra styling, and it removes code that lets the “Enter” button work, but not the “Space bar” so you can break common UI functionality with the space bar.

Also I noticed the mouse cursor shows if mouse capture is Disabled, or if that CVar that forces mouse to always show is set. I guess that’s that mouse cursor thing you’re talking about that needs an engine mod? It almost sounds like that behavior makes sense. You just have to stop manually calling set input mode game and UI, and setting the cursor visible.

1 Like