mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 17:45:23 +00:00
Refactor input image lookup logic into GameSubsystem so it can be reused elsewhere
This commit is contained in:
parent
70bce95d3b
commit
a2ca3076e9
@ -4,7 +4,10 @@
|
||||
#include "Engine/AssetManager.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "GameFramework/InputSettings.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/PlayerInput.h"
|
||||
#include "StevesUI/KeySprite.h"
|
||||
|
||||
//PRAGMA_DISABLE_OPTIMIZATION
|
||||
|
||||
@ -92,6 +95,102 @@ FFocusSystem* UStevesGameSubsystem::GetFocusSystem()
|
||||
return &FocusSystem;
|
||||
}
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetInputImageSprite(EInputBindingType BindingType, FName ActionOrAxis,
|
||||
FKey Key, int PlayerIdx, const UUiTheme* Theme)
|
||||
{
|
||||
switch(BindingType)
|
||||
{
|
||||
case EInputBindingType::Action:
|
||||
return GetInputImageSpriteFromAction(ActionOrAxis, PlayerIdx, Theme);
|
||||
case EInputBindingType::Axis:
|
||||
return GetInputImageSpriteFromAxis(ActionOrAxis, PlayerIdx, Theme);
|
||||
case EInputBindingType::Key:
|
||||
return GetInputImageSpriteFromKey(Key, Theme);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// This is not threadsafe! But only used in UI thread in practice
|
||||
TArray<FInputActionKeyMapping> GS_TempActionMap;
|
||||
TArray<FInputAxisKeyMapping> GS_TempAxisMap;
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetInputImageSpriteFromAction(const FName& Name, int PlayerIdx, const UUiTheme* Theme)
|
||||
{
|
||||
|
||||
// Look up the key for this action
|
||||
UInputSettings* Settings = UInputSettings::GetInputSettings();
|
||||
GS_TempActionMap.Empty();
|
||||
Settings->GetActionMappingByName(Name, GS_TempActionMap);
|
||||
const bool WantGamepad = LastInputWasGamePad(PlayerIdx);
|
||||
for (auto && ActionMap : GS_TempActionMap)
|
||||
{
|
||||
if (ActionMap.Key.IsGamepadKey() == WantGamepad)
|
||||
{
|
||||
return GetInputImageSpriteFromKey(ActionMap.Key, Theme);
|
||||
}
|
||||
}
|
||||
// if we fell through, didn't find a mapping which matched our gamepad preference
|
||||
if (GS_TempActionMap.Num())
|
||||
{
|
||||
return GetInputImageSpriteFromKey(GS_TempActionMap[0].Key, Theme);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetInputImageSpriteFromAxis(const FName& Name, int PlayerIdx, const UUiTheme* Theme)
|
||||
{
|
||||
// Look up the key for this axis
|
||||
UInputSettings* Settings = UInputSettings::GetInputSettings();
|
||||
GS_TempAxisMap.Empty();
|
||||
Settings->GetAxisMappingByName(Name, GS_TempAxisMap);
|
||||
const bool WantGamepad = LastInputWasGamePad(PlayerIdx);
|
||||
for (auto && AxisMap : GS_TempAxisMap)
|
||||
{
|
||||
if (AxisMap.Key.IsGamepadKey() == WantGamepad)
|
||||
{
|
||||
return GetInputImageSpriteFromKey(AxisMap.Key, Theme);
|
||||
}
|
||||
}
|
||||
// if we fell through, didn't find a mapping which matched our gamepad preference
|
||||
if (GS_TempAxisMap.Num())
|
||||
{
|
||||
return GetInputImageSpriteFromKey(GS_TempAxisMap[0].Key, Theme);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetInputImageSpriteFromKey(const FKey& InKey, const UUiTheme* Theme)
|
||||
{
|
||||
if (!IsValid(Theme))
|
||||
Theme = GetDefaultUiTheme();
|
||||
|
||||
if (Theme)
|
||||
{
|
||||
if (InKey.IsGamepadKey())
|
||||
return GetImageSpriteFromTable(InKey, Theme->XboxControllerImages);
|
||||
else
|
||||
return GetImageSpriteFromTable(InKey, Theme->KeyboardMouseImages);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetImageSpriteFromTable(const FKey& InKey,
|
||||
const TSoftObjectPtr<UDataTable>& Asset)
|
||||
{
|
||||
// Sync load for simplicity for now
|
||||
const auto Table = Asset.LoadSynchronous();
|
||||
// Rows are named the same as the key name
|
||||
const auto SpriteRow = Table->FindRow<FKeySprite>(InKey.GetFName(), "Find Key Image");
|
||||
if (SpriteRow)
|
||||
{
|
||||
return SpriteRow->Sprite;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UStevesGameSubsystem::FInputModeDetector::FInputModeDetector()
|
||||
{
|
||||
// 4 local players should be plenty usually (will expand if necessary)
|
||||
|
@ -15,17 +15,20 @@ TSharedRef<SWidget> UInputImage::RebuildWidget()
|
||||
if (GS)
|
||||
{
|
||||
GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
||||
CurrentInputMode = GS->GetLastInputModeUsed();
|
||||
CurrentInputMode = GS->GetLastInputModeUsed(PlayerIndex);
|
||||
UpdateImage();
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void UInputImage::OnInputModeChanged(int PlayerIndex, EInputMode InputMode)
|
||||
void UInputImage::OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode)
|
||||
{
|
||||
CurrentInputMode = InputMode;
|
||||
UpdateImage();
|
||||
if (ChangedPlayerIdx == PlayerIndex)
|
||||
{
|
||||
CurrentInputMode = InputMode;
|
||||
UpdateImage();
|
||||
}
|
||||
}
|
||||
|
||||
void UInputImage::SetCustomTheme(UUiTheme* Theme)
|
||||
@ -68,102 +71,15 @@ void UInputImage::SetFromKey(FKey K)
|
||||
|
||||
void UInputImage::UpdateImage()
|
||||
{
|
||||
switch(BindingType)
|
||||
{
|
||||
case EInputBindingType::Action:
|
||||
UpdateImageFromAction(ActionOrAxisName);
|
||||
break;
|
||||
case EInputBindingType::Axis:
|
||||
UpdateImageFromAxis(ActionOrAxisName);
|
||||
break;
|
||||
case EInputBindingType::Key:
|
||||
UpdateImageFromKey(Key);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
}
|
||||
TArray<FInputActionKeyMapping> TempActionMap;
|
||||
TArray<FInputAxisKeyMapping> TempAxisMap;
|
||||
|
||||
void UInputImage::UpdateImageFromAction(const FName& Name)
|
||||
{
|
||||
// Look up the key for this action
|
||||
UInputSettings* Settings = UInputSettings::GetInputSettings();
|
||||
TempActionMap.Empty();
|
||||
Settings->GetActionMappingByName(Name, TempActionMap);
|
||||
const bool WantGamepad = CurrentInputMode == EInputMode::Gamepad;
|
||||
for (auto && ActionMap : TempActionMap)
|
||||
{
|
||||
if (ActionMap.Key.IsGamepadKey() == WantGamepad)
|
||||
{
|
||||
UpdateImageFromKey(ActionMap.Key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we fell through, didn't find a mapping which matched our gamepad preference
|
||||
if (TempActionMap.Num())
|
||||
{
|
||||
UpdateImageFromKey(TempActionMap[0].Key);
|
||||
}
|
||||
}
|
||||
|
||||
void UInputImage::UpdateImageFromAxis(const FName& Name)
|
||||
{
|
||||
// Look up the key for this axis
|
||||
UInputSettings* Settings = UInputSettings::GetInputSettings();
|
||||
TempAxisMap.Empty();
|
||||
Settings->GetAxisMappingByName(Name, TempAxisMap);
|
||||
const bool WantGamepad = CurrentInputMode == EInputMode::Gamepad;
|
||||
for (auto && AxisMap : TempAxisMap)
|
||||
{
|
||||
if (AxisMap.Key.IsGamepadKey() == WantGamepad)
|
||||
{
|
||||
UpdateImageFromKey(AxisMap.Key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we fell through, didn't find a mapping which matched our gamepad preference
|
||||
if (TempAxisMap.Num())
|
||||
{
|
||||
UpdateImageFromKey(TempAxisMap[0].Key);
|
||||
}
|
||||
}
|
||||
|
||||
void UInputImage::UpdateImageFromKey(const FKey& InKey)
|
||||
{
|
||||
auto T = GetTheme();
|
||||
if (T)
|
||||
{
|
||||
if (InKey.IsGamepadKey())
|
||||
UpdateImageFromTable(InKey, T->XboxControllerImages);
|
||||
else
|
||||
UpdateImageFromTable(InKey, T->KeyboardMouseImages);
|
||||
}
|
||||
}
|
||||
|
||||
void UInputImage::UpdateImageFromTable(const FKey& InKey, const TSoftObjectPtr<UDataTable>& Asset)
|
||||
{
|
||||
// Sync load for simplicity for now
|
||||
const auto Table = Asset.LoadSynchronous();
|
||||
// Rows are named the same as the key name
|
||||
const auto SpriteRow = Table->FindRow<FKeySprite>(InKey.GetFName(), "Find Key Image");
|
||||
if (SpriteRow)
|
||||
{
|
||||
// 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
|
||||
SetBrushFromAtlasInterface(SpriteRow->Sprite, true);
|
||||
}
|
||||
}
|
||||
|
||||
UUiTheme* UInputImage::GetTheme()
|
||||
{
|
||||
if (IsValid(CustomTheme))
|
||||
return CustomTheme;
|
||||
|
||||
auto GS = GetStevesGameSubsystem(GetWorld());
|
||||
if (GS)
|
||||
return GS->GetDefaultUiTheme();
|
||||
|
||||
return nullptr;
|
||||
{
|
||||
auto Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, PlayerIndex, CustomTheme);
|
||||
if (Sprite)
|
||||
{
|
||||
// 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
|
||||
SetBrushFromAtlasInterface(Sprite, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "InputCoreTypes.h"
|
||||
#include "PaperSprite.h"
|
||||
#include "Framework/Application/IInputProcessor.h"
|
||||
#include "StevesHelperCommon.h"
|
||||
#include "StevesUI/FocusSystem.h"
|
||||
@ -103,7 +104,9 @@ protected:
|
||||
|
||||
// Called by detector
|
||||
void OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode);
|
||||
|
||||
|
||||
UPaperSprite* GetImageSpriteFromTable(const FKey& Key, const TSoftObjectPtr<UDataTable>& Asset);
|
||||
|
||||
public:
|
||||
|
||||
/// Event raised when input mode changed between gamepad and keyboard / mouse
|
||||
@ -125,4 +128,42 @@ public:
|
||||
|
||||
/// Get the global focus system
|
||||
FFocusSystem* GetFocusSystem();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get an input button / key / axis image as a sprite based on any combination of action / axis binding or manual key
|
||||
* @param BindingType The type of input binding to look up
|
||||
* @param ActionOrAxis The name of the action or axis, if BindingType is looking for that
|
||||
* @param Key The explicit key you want to display, if the BindingType is set to custom key
|
||||
* @param PlayerIndex The player index to look up the binding for
|
||||
* @param Theme Optional explicit theme, if blank use the default theme
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable)
|
||||
UPaperSprite* GetInputImageSprite(EInputBindingType BindingType, FName ActionOrAxis, FKey Key, int PlayerIndex = 0, const UUiTheme* Theme = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get an input button / key image from an action
|
||||
* @param Name The name of the action
|
||||
* @param PlayerIndex The player index to look up the binding for
|
||||
* @param Theme Optional explicit theme, if blank use the default theme
|
||||
* @return
|
||||
*/
|
||||
UPaperSprite* GetInputImageSpriteFromAction(const FName& Name, int PlayerIndex = 0, const UUiTheme* Theme = nullptr);
|
||||
/**
|
||||
* @brief Get an input image from an axis
|
||||
* @param Name The name of the axis
|
||||
* @param PlayerIndex The player index to look up the binding for
|
||||
* @param Theme Optional explicit theme, if blank use the default theme
|
||||
* @return
|
||||
*/
|
||||
UPaperSprite* GetInputImageSpriteFromAxis(const FName& Name, int PlayerIndex = 0, const UUiTheme* Theme = nullptr);
|
||||
/**
|
||||
* @brief Get an input image for a specific key
|
||||
* @param Key The key to look up
|
||||
* @param Theme Optional explicit theme, if blank use the default theme
|
||||
* @return
|
||||
*/
|
||||
UPaperSprite* GetInputImageSpriteFromKey(const FKey& Key, const UUiTheme* Theme = nullptr);
|
||||
|
||||
};
|
||||
|
@ -38,3 +38,14 @@ enum class EGamePauseChange : uint8
|
||||
Unpaused UMETA(DisplayName="Unpause Game")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EInputBindingType : uint8
|
||||
{
|
||||
/// A button action, will be looked up based on input mappings
|
||||
Action = 0,
|
||||
/// An axis action, will be looked up based on input mappings
|
||||
Axis = 1,
|
||||
/// A manually specified FKey (which can be key, button, axis)
|
||||
Key = 2
|
||||
};
|
||||
|
||||
|
@ -7,18 +7,6 @@
|
||||
#include "StevesHelperCommon.h"
|
||||
#include "InputImage.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EInputBindingType : uint8
|
||||
{
|
||||
/// A button action, will be looked up based on input mappings
|
||||
Action = 0,
|
||||
/// An axis action, will be looked up based on input mappings
|
||||
Axis = 1,
|
||||
/// A manually specified FKey (which can be key, button, axis)
|
||||
Key = 2
|
||||
};
|
||||
|
||||
|
||||
/// A special widget containing an image which populates itself based on an input action / axis and can dynamically
|
||||
/// change based on the active input method.
|
||||
UCLASS()
|
||||
@ -39,6 +27,10 @@ protected:
|
||||
UPROPERTY(EditAnywhere)
|
||||
FKey Key;
|
||||
|
||||
/// The player index for which the input should be looked up
|
||||
UPROPERTY(EditAnywhere)
|
||||
int PlayerIndex = 0;
|
||||
|
||||
/// Custom theme to use for this input image set; if not supplied will use UStevesGameSubsystem::DefaultUiTheme
|
||||
UPROPERTY(EditAnywhere)
|
||||
UUiTheme* CustomTheme;
|
||||
@ -80,14 +72,9 @@ public:
|
||||
protected:
|
||||
|
||||
virtual TSharedRef<SWidget> RebuildWidget() override;
|
||||
void UpdateImageFromAction(const FName& Name);
|
||||
void UpdateImageFromAxis(const FName& Name);
|
||||
void UpdateImageFromTable(const FKey& Key, const TSoftObjectPtr<UDataTable>& Asset);
|
||||
void UpdateImageFromKey(const FKey& Key);
|
||||
virtual void UpdateImage();
|
||||
virtual UUiTheme* GetTheme();
|
||||
|
||||
UFUNCTION()
|
||||
void OnInputModeChanged(int PlayerIndex, EInputMode InputMode);
|
||||
void OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode);
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user