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/AssetManager.h"
|
||||||
#include "Engine/GameInstance.h"
|
#include "Engine/GameInstance.h"
|
||||||
#include "Framework/Application/SlateApplication.h"
|
#include "Framework/Application/SlateApplication.h"
|
||||||
|
#include "GameFramework/InputSettings.h"
|
||||||
#include "GameFramework/PlayerController.h"
|
#include "GameFramework/PlayerController.h"
|
||||||
|
#include "GameFramework/PlayerInput.h"
|
||||||
|
#include "StevesUI/KeySprite.h"
|
||||||
|
|
||||||
//PRAGMA_DISABLE_OPTIMIZATION
|
//PRAGMA_DISABLE_OPTIMIZATION
|
||||||
|
|
||||||
@ -92,6 +95,102 @@ FFocusSystem* UStevesGameSubsystem::GetFocusSystem()
|
|||||||
return &FocusSystem;
|
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()
|
UStevesGameSubsystem::FInputModeDetector::FInputModeDetector()
|
||||||
{
|
{
|
||||||
// 4 local players should be plenty usually (will expand if necessary)
|
// 4 local players should be plenty usually (will expand if necessary)
|
||||||
|
@ -15,17 +15,20 @@ TSharedRef<SWidget> UInputImage::RebuildWidget()
|
|||||||
if (GS)
|
if (GS)
|
||||||
{
|
{
|
||||||
GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
||||||
CurrentInputMode = GS->GetLastInputModeUsed();
|
CurrentInputMode = GS->GetLastInputModeUsed(PlayerIndex);
|
||||||
UpdateImage();
|
UpdateImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UInputImage::OnInputModeChanged(int PlayerIndex, EInputMode InputMode)
|
void UInputImage::OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode)
|
||||||
{
|
{
|
||||||
CurrentInputMode = InputMode;
|
if (ChangedPlayerIdx == PlayerIndex)
|
||||||
UpdateImage();
|
{
|
||||||
|
CurrentInputMode = InputMode;
|
||||||
|
UpdateImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UInputImage::SetCustomTheme(UUiTheme* Theme)
|
void UInputImage::SetCustomTheme(UUiTheme* Theme)
|
||||||
@ -68,102 +71,15 @@ void UInputImage::SetFromKey(FKey K)
|
|||||||
|
|
||||||
void UInputImage::UpdateImage()
|
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());
|
auto GS = GetStevesGameSubsystem(GetWorld());
|
||||||
if (GS)
|
if (GS)
|
||||||
return GS->GetDefaultUiTheme();
|
{
|
||||||
|
auto Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, PlayerIndex, CustomTheme);
|
||||||
return nullptr;
|
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 "CoreMinimal.h"
|
||||||
#include "Subsystems/GameInstanceSubsystem.h"
|
#include "Subsystems/GameInstanceSubsystem.h"
|
||||||
#include "InputCoreTypes.h"
|
#include "InputCoreTypes.h"
|
||||||
|
#include "PaperSprite.h"
|
||||||
#include "Framework/Application/IInputProcessor.h"
|
#include "Framework/Application/IInputProcessor.h"
|
||||||
#include "StevesHelperCommon.h"
|
#include "StevesHelperCommon.h"
|
||||||
#include "StevesUI/FocusSystem.h"
|
#include "StevesUI/FocusSystem.h"
|
||||||
@ -103,7 +104,9 @@ protected:
|
|||||||
|
|
||||||
// Called by detector
|
// Called by detector
|
||||||
void OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode);
|
void OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode);
|
||||||
|
|
||||||
|
UPaperSprite* GetImageSpriteFromTable(const FKey& Key, const TSoftObjectPtr<UDataTable>& Asset);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Event raised when input mode changed between gamepad and keyboard / mouse
|
/// Event raised when input mode changed between gamepad and keyboard / mouse
|
||||||
@ -125,4 +128,42 @@ public:
|
|||||||
|
|
||||||
/// Get the global focus system
|
/// Get the global focus system
|
||||||
FFocusSystem* GetFocusSystem();
|
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")
|
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 "StevesHelperCommon.h"
|
||||||
#include "InputImage.generated.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
|
/// 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.
|
/// change based on the active input method.
|
||||||
UCLASS()
|
UCLASS()
|
||||||
@ -39,6 +27,10 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere)
|
UPROPERTY(EditAnywhere)
|
||||||
FKey Key;
|
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
|
/// Custom theme to use for this input image set; if not supplied will use UStevesGameSubsystem::DefaultUiTheme
|
||||||
UPROPERTY(EditAnywhere)
|
UPROPERTY(EditAnywhere)
|
||||||
UUiTheme* CustomTheme;
|
UUiTheme* CustomTheme;
|
||||||
@ -80,14 +72,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual TSharedRef<SWidget> RebuildWidget() override;
|
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 void UpdateImage();
|
||||||
virtual UUiTheme* GetTheme();
|
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnInputModeChanged(int PlayerIndex, EInputMode InputMode);
|
void OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user