CommonUI EnhancedInput
As you know, it’s possible to use Enhanced Input for keys with Common UI since a few versions of UE5.
However, as mentioned, some personal work is likely needed to fully integrate it because, by default, you need to activate an InputMappingContext in the UCommonActivatableWidget.
It works, but you’ll run into issues in certain cases, for example:
- You have two UCommonActivatableWidget instances. If you activate the second one, the InputMappingContext from the first one will be removed, so you’ll lose the InputMappingContext, even if you specified it in the second UCommonActivatableWidget.
My Solution
For now, in my plugin, I inherit from UCommonActivatableWidget to add functionality, including managing a global IMC (InputMappingContext) with a pooling system to avoid the problem mentioned earlier.
Code Explain
To briefly explain the code: I have a Subsystem that retrieves your IMC through your DefaultGame.ini file and includes functions like PullGlobalMappingContext and PopGlobalMappingContext.
Struct for pull
USTRUCT(BlueprintType)
struct SOMNDUSGAME_API FSSInputMappingContextPullToken
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
const UInputMappingContext* MappingContext;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Token;
};
Subsystem with the pull array
UCLASS(config = Game)
class SOMNDUSGAME_API USSInputLocalPlayerSubsystem : public ULocalPlayerSubsystem
{
GENERATED_BODY()
public:
...
UPROPERTY()
TArray<FSSInputMappingContextPullToken> InputMappingContextPullTokens;
Global IMC for CommonUI
In my USSInputLocalPlayerSubsystem
/**
* To use in every activatable widget instead specific one by one
*/
UPROPERTY(config, EditAnywhere)
TSoftObjectPtr<UInputMappingContext> GenericUIMappingContextSoft;
Example in DefaultGame.ini
[/Script/SomndusGame.SSInputLocalPlayerSubsystem]
GenericUIMappingContextSoft=/Game/Input/IMC_CommonMenu.IMC_CommonMenu
How USSGameActivatableWidget use it
NativeOnActivated
I’ll briefly explain how my ActivatableWidget works. In short, it pulls using a token (which will be the name of the instantiated widget). The pulling system checks whether to add or remove the global IMC based on whether any tokens remain in the pull array.
void USSGameActivatableWidget::NativeOnActivated()
{
Super::NativeOnActivated();
if (CommonUI::IsEnhancedInputSupportEnabled())
{
if (const ULocalPlayer* LocalPlayer = GetOwningLocalPlayer())
{
if (USSInputLocalPlayerSubsystem* InputSystem = LocalPlayer->GetSubsystem<USSInputLocalPlayerSubsystem>())
{
InputSystem->PullGlobalMappingContext(GetInputToken());
}
}
}
}
NativeOnDeactivated
void USSGameActivatableWidget::NativeOnDeactivated()
{
Super::NativeOnDeactivated();
if (CommonUI::IsEnhancedInputSupportEnabled())
{
if (const ULocalPlayer* LocalPlayer = GetOwningLocalPlayer())
{
if (USSInputLocalPlayerSubsystem* InputSystem = LocalPlayer->GetSubsystem<USSInputLocalPlayerSubsystem>())
{
InputSystem->PopGlobalMappingContext(GetInputToken());
}
}
}
}