Workaround for the problem that EnhancedInput does not tell you when contexts / mappings change

This commit is contained in:
Steve Streeting 2023-03-07 16:34:39 +00:00
parent 9e4b77d518
commit 0aea6933dc
4 changed files with 53 additions and 2 deletions

View File

@ -22,6 +22,7 @@ void UStevesGameSubsystem::Initialize(FSubsystemCollectionBase& Collection)
CreateInputDetector(); CreateInputDetector();
InitTheme(); InitTheme();
InitForegroundCheck(); InitForegroundCheck();
NotifyEnhancedInputMappingsChanged();
#endif #endif
} }
@ -60,6 +61,17 @@ void UStevesGameSubsystem::DestroyInputDetector()
#endif #endif
} }
void UStevesGameSubsystem::NotifyEnhancedInputMappingsChanged()
{
// delay to ensure there's a tick in between which updates the mappings, it's not synchronous
auto DelayedFunc = [this]()
{
OnEnhancedInputMappingsChanged.Broadcast();
};
FTimerHandle TempHandle;
GetWorld()->GetTimerManager().SetTimer(TempHandle, FTimerDelegate::CreateLambda(DelayedFunc), 0.05, false);
}
void UStevesGameSubsystem::InitTheme() void UStevesGameSubsystem::InitTheme()
{ {
DefaultUiTheme = LoadObject<UUiTheme>(nullptr, *DefaultUiThemePath, nullptr); DefaultUiTheme = LoadObject<UUiTheme>(nullptr, *DefaultUiThemePath, nullptr);

View File

@ -12,12 +12,13 @@ TSharedRef<SWidget> UInputImage::RebuildWidget()
auto GS = GetStevesGameSubsystem(GetWorld()); auto GS = GetStevesGameSubsystem(GetWorld());
if (GS && !bSubbedToInputEvents) if (GS && !bSubbedToInputEvents)
{ {
bSubbedToInputEvents = true;
GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged); GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
GS->OnButtonInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged); GS->OnButtonInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
GS->OnAxisInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged); GS->OnAxisInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
GS->OnEnhancedInputMappingsChanged.AddUniqueDynamic(this, &UInputImage::OnEnhancedInputMappingsChanged);
} }
bSubbedToInputEvents = true;
UpdateImage(); UpdateImage();
return Ret; return Ret;
@ -36,6 +37,11 @@ void UInputImage::OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode)
} }
} }
void UInputImage::OnEnhancedInputMappingsChanged()
{
MarkImageDirty();
}
void UInputImage::SetCustomTheme(UUiTheme* Theme) void UInputImage::SetCustomTheme(UUiTheme* Theme)
{ {
CustomTheme = Theme; CustomTheme = Theme;
@ -120,10 +126,24 @@ void UInputImage::UpdateImage()
if (Sprite) if (Sprite)
{ {
if (bHiddenBecauseBlank)
{
SetVisibility(OldVisibility);
bHiddenBecauseBlank = false;
}
// Match size is needed incase size has changed // Match size is needed incase size has changed
// Need to make it update region in case inside a scale box or something else that needs to adjust // Need to make it update region in case inside a scale box or something else that needs to adjust
SetBrushFromAtlasInterface(Sprite, true); SetBrushFromAtlasInterface(Sprite, true);
} }
else
{
if (IsVisible())
{
bHiddenBecauseBlank = true;
OldVisibility = GetVisibility();
SetVisibility(ESlateVisibility::Hidden);
}
}
} }
bIsDirty = false; bIsDirty = false;
DelayUpdate = 0; DelayUpdate = 0;
@ -132,7 +152,7 @@ void UInputImage::UpdateImage()
void UInputImage::MarkImageDirty() void UInputImage::MarkImageDirty()
{ {
bIsDirty = true; bIsDirty = true;
DelayUpdate = 0.5f; DelayUpdate = 0.1f;
} }
// Tickables // Tickables

View File

@ -14,6 +14,7 @@
#include "StevesGameSubsystem.generated.h" #include "StevesGameSubsystem.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEnhancedInputMappingsChanged);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowForegroundChanged, bool, bFocussed); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowForegroundChanged, bool, bFocussed);
/// Entry point for all the top-level features of the helper system /// Entry point for all the top-level features of the helper system
@ -160,6 +161,12 @@ public:
/// last axis moved was still mouse, you'd get this event later /// last axis moved was still mouse, you'd get this event later
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FOnInputModeChanged OnAxisInputModeChanged; FOnInputModeChanged OnAxisInputModeChanged;
/// Event raised justr after the Enhanced Input mappings have changed
/// Right now, this has to be user-triggered via NotifyEnhancedInputMappingsChanged, because the Enhanced Input
/// plugin provides NO events to monitor it (sigh)
UPROPERTY(BlueprintAssignable)
FOnEnhancedInputMappingsChanged OnEnhancedInputMappingsChanged;
/// Event raised when the game window's foreground status changes /// Event raised when the game window's foreground status changes
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
@ -277,4 +284,12 @@ public:
*/ */
FStevesTextureRenderTargetPoolPtr GetTextureRenderTargetPool(FName Name, bool bAutoCreate = true); FStevesTextureRenderTargetPoolPtr GetTextureRenderTargetPool(FName Name, bool bAutoCreate = true);
/**
* Notify this subsystem that changes have been made to the Enhanced Input mappings, e.g. adding or removing a context.
* Unfortunately, the Enhanced Input plugin currently provides NO WAY for us to monitor context changes automatically,
* so we need the user to tell us when they make a change.
* This call is however slightly delayed before being acted upon, because EI defers the rebuild of mappings until the next tick.
*/
void NotifyEnhancedInputMappingsChanged();
}; };

View File

@ -46,6 +46,8 @@ protected:
bool bSubbedToInputEvents = false; bool bSubbedToInputEvents = false;
bool bIsDirty = true; bool bIsDirty = true;
float DelayUpdate = 0; float DelayUpdate = 0;
bool bHiddenBecauseBlank;
ESlateVisibility OldVisibility;
public: public:
@ -104,5 +106,7 @@ protected:
UFUNCTION() UFUNCTION()
void OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode); void OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode);
UFUNCTION()
void OnEnhancedInputMappingsChanged();
}; };