mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 17:45:23 +00:00
Merge branch 'enhanced-input'
This commit is contained in:
commit
46e1a18187
@ -1,5 +1,9 @@
|
||||
#include "StevesGameSubsystem.h"
|
||||
|
||||
#include "EngineUtils.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "StevesGameViewportClientBase.h"
|
||||
#include "StevesPluginSettings.h"
|
||||
#include "StevesUEHelpers.h"
|
||||
#include "Engine/AssetManager.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
@ -20,6 +24,7 @@ void UStevesGameSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
CreateInputDetector();
|
||||
InitTheme();
|
||||
InitForegroundCheck();
|
||||
NotifyEnhancedInputMappingsChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -58,6 +63,50 @@ void UStevesGameSubsystem::DestroyInputDetector()
|
||||
#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);
|
||||
}
|
||||
|
||||
TSoftObjectPtr<UInputAction> UStevesGameSubsystem::FindEnhancedInputAction(const FString& Name)
|
||||
{
|
||||
if (FAssetRegistryModule* AssetRegistryModule = FModuleManager::LoadModulePtr<FAssetRegistryModule>(TEXT("AssetRegistry")))
|
||||
{
|
||||
IAssetRegistry& AssetRegistry = AssetRegistryModule->Get();
|
||||
if (auto Settings = GetDefault<UStevesPluginSettings>())
|
||||
{
|
||||
for (const auto& Dir : Settings->EnhancedInputActionSearchDirectories)
|
||||
{
|
||||
if (!FPackageName::IsValidPath(Dir.Path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TArray<FAssetData> Assets;
|
||||
FString Package = FPaths::Combine(Dir.Path, Name);
|
||||
if (AssetRegistry.GetAssetsByPackageName(FName(*Package), Assets, true))
|
||||
{
|
||||
for (const FAssetData& Asset : Assets)
|
||||
{
|
||||
if (Asset.GetClass() == UInputAction::StaticClass())
|
||||
{
|
||||
return TSoftObjectPtr<UInputAction>(Asset.GetSoftObjectPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UStevesGameSubsystem::InitTheme()
|
||||
{
|
||||
DefaultUiTheme = LoadObject<UUiTheme>(nullptr, *DefaultUiThemePath, nullptr);
|
||||
@ -224,6 +273,42 @@ UPaperSprite* UStevesGameSubsystem::GetInputImageSpriteFromAxis(const FName& Nam
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UPaperSprite* UStevesGameSubsystem::GetInputImageSpriteFromEnhancedInputAction(UInputAction* Action,
|
||||
EInputImageDevicePreference DevicePreference,
|
||||
int PlayerIdx,
|
||||
APlayerController* PC,
|
||||
UUiTheme* Theme)
|
||||
{
|
||||
|
||||
if (const UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
|
||||
{
|
||||
const TArray<FKey> Keys = Subsystem->QueryKeysMappedToAction(Action);
|
||||
|
||||
// For default, prefer mouse for axes
|
||||
if (DevicePreference == EInputImageDevicePreference::Auto)
|
||||
{
|
||||
if (Action->ValueType == EInputActionValueType::Boolean)
|
||||
{
|
||||
DevicePreference = EInputImageDevicePreference::Gamepad_Keyboard_Mouse_Button;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevicePreference = EInputImageDevicePreference::Gamepad_Mouse_Keyboard;
|
||||
}
|
||||
}
|
||||
const EInputMode LastInput = GetLastInputModeUsed(PlayerIdx);
|
||||
const EInputMode LastButtonInput = GetLastInputButtonPressed(PlayerIdx);
|
||||
const EInputMode LastAxisInput = GetLastInputAxisMoved(PlayerIdx);
|
||||
if (const FKey* PreferredKey = GetPreferedKeyMapping(Keys, DevicePreference, LastInput, LastButtonInput, LastAxisInput))
|
||||
{
|
||||
return GetInputImageSpriteFromKey(*PreferredKey, PlayerIdx, Theme);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
TSoftObjectPtr<UDataTable> UStevesGameSubsystem::GetGamepadImages(int PlayerIndex, const UUiTheme* Theme)
|
||||
{
|
||||
// TODO: determine type of controller
|
||||
|
4
Source/StevesUEHelpers/Private/StevesPluginSettings.cpp
Normal file
4
Source/StevesUEHelpers/Private/StevesPluginSettings.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "StevesPluginSettings.h"
|
@ -1,5 +1,9 @@
|
||||
#include "StevesUEHelpers.h"
|
||||
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "StevesPluginSettings.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FStevesUEHelpers"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogStevesUEHelpers)
|
||||
@ -8,6 +12,19 @@ void FStevesUEHelpers::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
UE_LOG(LogStevesUEHelpers, Log, TEXT("Steve's UE Helpers Module Started"))
|
||||
|
||||
// register settings
|
||||
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
|
||||
|
||||
if (SettingsModule)
|
||||
{
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule->RegisterSettings("Project", "Plugins", "StevesUEHelpers",
|
||||
LOCTEXT("StevesUEHelpersSettingsName", "StevesUEHelpers"),
|
||||
LOCTEXT("StevesUEHelpersSettingsDescription", "Configure the helpers plug-in."),
|
||||
GetMutableDefault<UStevesPluginSettings>()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FStevesUEHelpers::ShutdownModule()
|
||||
|
@ -16,7 +16,9 @@ TSharedRef<SWidget> UInputImage::RebuildWidget()
|
||||
GS->OnInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
||||
GS->OnButtonInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
||||
GS->OnAxisInputModeChanged.AddUniqueDynamic(this, &UInputImage::OnInputModeChanged);
|
||||
GS->OnEnhancedInputMappingsChanged.AddUniqueDynamic(this, &UInputImage::OnEnhancedInputMappingsChanged);
|
||||
}
|
||||
|
||||
UpdateImage();
|
||||
|
||||
return Ret;
|
||||
@ -35,6 +37,11 @@ void UInputImage::OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode)
|
||||
}
|
||||
}
|
||||
|
||||
void UInputImage::OnEnhancedInputMappingsChanged()
|
||||
{
|
||||
MarkImageDirty();
|
||||
}
|
||||
|
||||
void UInputImage::SetCustomTheme(UUiTheme* Theme)
|
||||
{
|
||||
CustomTheme = Theme;
|
||||
@ -94,18 +101,51 @@ void UInputImage::SetFromKey(FKey K)
|
||||
UpdateImage();
|
||||
}
|
||||
|
||||
void UInputImage::SetFromInputAction(UInputAction* Action)
|
||||
{
|
||||
BindingType = EInputBindingType::EnhancedInputAction;
|
||||
InputAction = Action;
|
||||
UpdateImage();
|
||||
}
|
||||
|
||||
void UInputImage::UpdateImage()
|
||||
{
|
||||
auto GS = GetStevesGameSubsystem(GetWorld());
|
||||
if (GS)
|
||||
{
|
||||
auto Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, DevicePreference, PlayerIndex, CustomTheme);
|
||||
UPaperSprite* Sprite = nullptr;
|
||||
if (BindingType == EInputBindingType::EnhancedInputAction && !InputAction.IsNull())
|
||||
{
|
||||
if (auto IA = InputAction.LoadSynchronous())
|
||||
{
|
||||
Sprite = GS->GetInputImageSpriteFromEnhancedInputAction(IA, DevicePreference, PlayerIndex, GetOwningPlayer(), CustomTheme);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, DevicePreference, PlayerIndex, CustomTheme);
|
||||
}
|
||||
|
||||
if (Sprite)
|
||||
{
|
||||
if (bHiddenBecauseBlank)
|
||||
{
|
||||
SetVisibility(OldVisibility);
|
||||
bHiddenBecauseBlank = false;
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsVisible())
|
||||
{
|
||||
bHiddenBecauseBlank = true;
|
||||
OldVisibility = GetVisibility();
|
||||
SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
bIsDirty = false;
|
||||
DelayUpdate = 0;
|
||||
@ -114,7 +154,7 @@ void UInputImage::UpdateImage()
|
||||
void UInputImage::MarkImageDirty()
|
||||
{
|
||||
bIsDirty = true;
|
||||
DelayUpdate = 0.5f;
|
||||
DelayUpdate = 0.1f;
|
||||
}
|
||||
|
||||
// Tickables
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "StevesHelperCommon.h"
|
||||
#include "StevesUEHelpers.h"
|
||||
#include "Fonts/FontMeasure.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Misc/DefaultValueHelper.h"
|
||||
#include "Widgets/Layout/SScaleBox.h"
|
||||
#include "Widgets/Images/SImage.h"
|
||||
@ -18,6 +19,8 @@ struct FRichTextInputImageParams
|
||||
FName ActionOrAxisName;
|
||||
/// If BindingType is Key, the key
|
||||
FKey Key;
|
||||
/// If binding type is EnhancedInputAction, a reference to an enhanced input action
|
||||
TSoftObjectPtr<UInputAction> InputAction;
|
||||
/// Player index, if binding type is action or axis
|
||||
int PlayerIndex;
|
||||
/// Where there are multiple mappings, which to prefer
|
||||
@ -38,6 +41,8 @@ protected:
|
||||
FName ActionOrAxisName;
|
||||
/// If BindingType is Key, the key
|
||||
FKey Key;
|
||||
/// If binding type is EnhancedInputAction, a reference to an enhanced input action
|
||||
TSoftObjectPtr<UInputAction> InputAction;
|
||||
/// Player index, if binding type is action or axis
|
||||
int PlayerIndex = 0;
|
||||
/// Where there are multiple mappings, which to prefer
|
||||
@ -66,6 +71,7 @@ public:
|
||||
ActionOrAxisName = InParams.ActionOrAxisName;
|
||||
DevicePreference = InParams.DevicePreference;
|
||||
Key = InParams.Key;
|
||||
InputAction = InParams.InputAction;
|
||||
PlayerIndex = InParams.PlayerIndex;
|
||||
Decorator = InParams.Decorator;
|
||||
RequestedWidth = Width;
|
||||
@ -77,7 +83,7 @@ public:
|
||||
// We will need to do the work to update the brush from the main thread later
|
||||
|
||||
// We can use static methods though
|
||||
if (InParams.InitialSprite)
|
||||
if (IsValid(InParams.InitialSprite))
|
||||
UStevesGameSubsystem::SetBrushFromAtlas(&Brush, InParams.InitialSprite, true);
|
||||
TimeUntilNextSpriteCheck = 0.25f;
|
||||
|
||||
@ -128,7 +134,19 @@ public:
|
||||
if (GS)
|
||||
{
|
||||
// Can only support default theme, no way to edit theme in decorator config
|
||||
auto Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, DevicePreference, PlayerIndex);
|
||||
UPaperSprite* Sprite = nullptr;
|
||||
if (BindingType == EInputBindingType::EnhancedInputAction && !InputAction.IsNull())
|
||||
{
|
||||
if (auto IA = InputAction.LoadSynchronous())
|
||||
{
|
||||
auto PC = UGameplayStatics::GetPlayerController(Decorator->GetWorld(), PlayerIndex);
|
||||
Sprite = GS->GetInputImageSpriteFromEnhancedInputAction(IA, DevicePreference, PlayerIndex, PC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprite = GS->GetInputImageSprite(BindingType, ActionOrAxisName, Key, DevicePreference, PlayerIndex);
|
||||
}
|
||||
if (Sprite && Brush.GetResourceObject() != Sprite)
|
||||
{
|
||||
UStevesGameSubsystem::SetBrushFromAtlas(&Brush, Sprite, true);
|
||||
@ -175,7 +193,8 @@ public:
|
||||
{
|
||||
return RunParseResult.MetaData.Contains(TEXT("key")) ||
|
||||
RunParseResult.MetaData.Contains(TEXT("action")) ||
|
||||
RunParseResult.MetaData.Contains(TEXT("axis"));
|
||||
RunParseResult.MetaData.Contains(TEXT("axis")) ||
|
||||
RunParseResult.MetaData.Contains(TEXT("eaction"));
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -191,6 +210,8 @@ protected:
|
||||
Params.Key = EKeys::AnyKey;
|
||||
Params.Decorator = Decorator;
|
||||
|
||||
auto GS = GetStevesGameSubsystem(Decorator->GetWorld());
|
||||
|
||||
if (const FString* PlayerStr = RunInfo.MetaData.Find(TEXT("player")))
|
||||
{
|
||||
int PTemp;
|
||||
@ -212,6 +233,15 @@ protected:
|
||||
Params.BindingType = EInputBindingType::Axis;
|
||||
Params.ActionOrAxisName = **AxisStr;
|
||||
}
|
||||
else if (const FString* EInputStr = RunInfo.MetaData.Find(TEXT("eaction")))
|
||||
{
|
||||
Params.BindingType = EInputBindingType::EnhancedInputAction;
|
||||
// Try to find the input action
|
||||
if (GS)
|
||||
{
|
||||
Params.InputAction = GS->FindEnhancedInputAction(*EInputStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (const FString* PreferStr = RunInfo.MetaData.Find(TEXT("prefer")))
|
||||
{
|
||||
@ -240,12 +270,22 @@ protected:
|
||||
// Look up the initial sprite here
|
||||
// The Slate widget can't do it in Construct because World pointer doesn't work (thread issues?)
|
||||
// Also annoying: can't keep Brush on this class because this method is const. UGH
|
||||
auto GS = GetStevesGameSubsystem(Decorator->GetWorld());
|
||||
if (GS)
|
||||
{
|
||||
if (Params.BindingType == EInputBindingType::EnhancedInputAction && !Params.InputAction.IsNull())
|
||||
{
|
||||
if (auto IA = Params.InputAction.LoadSynchronous())
|
||||
{
|
||||
auto PC = UGameplayStatics::GetPlayerController(Decorator->GetWorld(), Params.PlayerIndex);
|
||||
Params.InitialSprite = GS->GetInputImageSpriteFromEnhancedInputAction(IA, Params.DevicePreference, Params.PlayerIndex, PC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can only support default theme, no way to edit theme in decorator config
|
||||
Params.InitialSprite = GS->GetInputImageSprite(Params.BindingType, Params.ActionOrAxisName, Params.Key, Params.DevicePreference, Params.PlayerIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Might be false because this gets executed in the editor too
|
||||
|
@ -49,3 +49,67 @@ void SetWidgetFocusProperly(UWidget* Widget)
|
||||
Widget->SetFocus();
|
||||
|
||||
}
|
||||
|
||||
const FKey* GetPreferedKeyMapping(const TArray<FKey>& AllKeys,
|
||||
EInputImageDevicePreference DevicePreference,
|
||||
EInputMode LastInputDevice,
|
||||
EInputMode LastButtonInputDevice,
|
||||
EInputMode LastAxisInputDevice)
|
||||
{
|
||||
// Same as GetPreferedActionOrAxisMapping, just with key directly
|
||||
const FKey* MouseMapping = nullptr;
|
||||
const FKey* KeyboardMapping = nullptr;
|
||||
const FKey* GamepadMapping = nullptr;
|
||||
for (const FKey& Key : AllKeys)
|
||||
{
|
||||
// notice how we take the LAST one in the list as the final version
|
||||
// this is because UInputSettings::GetActionMappingByName *reverses* the mapping list from Project Settings
|
||||
if (Key.IsGamepadKey())
|
||||
{
|
||||
GamepadMapping = &Key;
|
||||
}
|
||||
else if (Key.IsMouseButton()) // registers true for mouse axes too
|
||||
{
|
||||
MouseMapping = &Key;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyboardMapping = &Key;
|
||||
}
|
||||
}
|
||||
|
||||
const FKey* Preferred = nullptr;
|
||||
if (GamepadMapping && LastInputDevice == EInputMode::Gamepad)
|
||||
{
|
||||
// Always prefer gamepad if used last
|
||||
Preferred = GamepadMapping;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (DevicePreference)
|
||||
{
|
||||
// Auto should be pre-converted to another
|
||||
case EInputImageDevicePreference::Auto:
|
||||
UE_LOG(LogStevesUI, Error, TEXT("Device Preference should have been converted before this call"))
|
||||
break;
|
||||
case EInputImageDevicePreference::Gamepad_Keyboard_Mouse:
|
||||
Preferred = KeyboardMapping ? KeyboardMapping : MouseMapping;
|
||||
break;
|
||||
case EInputImageDevicePreference::Gamepad_Mouse_Keyboard:
|
||||
Preferred = MouseMapping ? MouseMapping : KeyboardMapping;
|
||||
break;
|
||||
|
||||
case EInputImageDevicePreference::Gamepad_Keyboard_Mouse_Button:
|
||||
// Use the latest button press
|
||||
Preferred = (MouseMapping && (LastButtonInputDevice == EInputMode::Mouse || !KeyboardMapping)) ? MouseMapping : KeyboardMapping;
|
||||
break;
|
||||
case EInputImageDevicePreference::Gamepad_Keyboard_Mouse_Axis:
|
||||
// Use the latest button press
|
||||
Preferred = (MouseMapping && (LastAxisInputDevice == EInputMode::Mouse || !KeyboardMapping)) ? MouseMapping : KeyboardMapping;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Preferred;
|
||||
}
|
||||
|
@ -89,3 +89,10 @@ const T* GetPreferedActionOrAxisMapping(const TArray<T>& AllMappings, const FNam
|
||||
}
|
||||
return Preferred;
|
||||
}
|
||||
|
||||
|
||||
const FKey* GetPreferedKeyMapping(const TArray<FKey>& AllKeys,
|
||||
EInputImageDevicePreference DevicePreference,
|
||||
EInputMode LastInputDevice,
|
||||
EInputMode LastButtonInputDevice,
|
||||
EInputMode LastAxisInputDevice);
|
||||
|
@ -8,11 +8,13 @@
|
||||
#include "StevesHelperCommon.h"
|
||||
#include "StevesTextureRenderTargetPool.h"
|
||||
#include "StevesUI/FocusSystem.h"
|
||||
#include "StevesUI/InputImage.h"
|
||||
#include "StevesUI/UiTheme.h"
|
||||
|
||||
#include "StevesGameSubsystem.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEnhancedInputMappingsChanged);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowForegroundChanged, bool, bFocussed);
|
||||
|
||||
/// Entry point for all the top-level features of the helper system
|
||||
@ -37,7 +39,6 @@ public:
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
|
||||
|
||||
protected:
|
||||
DECLARE_DELEGATE_TwoParams(FInternalInputModeChanged, int /* PlayerIndex */, EInputMode)
|
||||
/**
|
||||
@ -161,6 +162,12 @@ public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
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
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnWindowForegroundChanged OnWindowForegroundChanged;
|
||||
@ -209,6 +216,21 @@ public:
|
||||
int PlayerIndex = 0,
|
||||
const UUiTheme* Theme = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get an input button / key / axis image as a sprite based on an enhanced input action
|
||||
* @param Action The input action
|
||||
* @param DevicePreference The order of preference for images where multiple devices have mappings. In the case of multiple mappings for the same device, the first one will be used.
|
||||
* @param PlayerIdx The player index to look up the binding for
|
||||
* @param PC The player controller to look up the binding for
|
||||
* @param Theme Optional explicit theme, if blank use the default theme
|
||||
* @return
|
||||
*/
|
||||
UPaperSprite* GetInputImageSpriteFromEnhancedInputAction(UInputAction* Action,
|
||||
EInputImageDevicePreference DevicePreference,
|
||||
int PlayerIdx,
|
||||
APlayerController* PC,
|
||||
UUiTheme* Theme = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get an input button / key image from an action
|
||||
* @param Name The name of the action
|
||||
@ -266,4 +288,16 @@ public:
|
||||
*/
|
||||
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();
|
||||
|
||||
/** Attempt to find an enhanced input action by name in the configured folders.
|
||||
*/
|
||||
TSoftObjectPtr<UInputAction> FindEnhancedInputAction(const FString& Name);
|
||||
|
||||
};
|
||||
|
@ -41,12 +41,14 @@ enum class EGamePauseChange : uint8
|
||||
UENUM(BlueprintType)
|
||||
enum class EInputBindingType : uint8
|
||||
{
|
||||
/// A button action, will be looked up based on input mappings
|
||||
/// A legacy button action, will be looked up based on input mappings
|
||||
Action = 0,
|
||||
/// An axis action, will be looked up based on input mappings
|
||||
/// An legacy axis action, will be looked up based on input mappings
|
||||
Axis = 1,
|
||||
/// A manually specified FKey (which can be key, button, axis)
|
||||
Key = 2
|
||||
Key = 2,
|
||||
/// An EnhancedInput action
|
||||
EnhancedInputAction = 3
|
||||
};
|
||||
|
||||
/// What order of preference should we return input images where an action/axis has multiple mappings
|
||||
|
23
Source/StevesUEHelpers/Public/StevesPluginSettings.h
Normal file
23
Source/StevesUEHelpers/Public/StevesPluginSettings.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "StevesPluginSettings.generated.h"
|
||||
|
||||
/**
|
||||
* Settings for the plug-in.
|
||||
*/
|
||||
UCLASS(config=Engine)
|
||||
class STEVESUEHELPERS_API UStevesPluginSettings
|
||||
: public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/// Which directories to search for Enhanced Input Actions when referenced just by name in e.g. Rich Text Decorator
|
||||
UPROPERTY(config, EditAnywhere, Category = StevesUEHelpers, meta = (DisplayName = "Directories to search for Enhanced Input Actions", RelativeToGameContentDir, LongPackageName))
|
||||
TArray<FDirectoryPath> EnhancedInputActionSearchDirectories;
|
||||
|
||||
UStevesPluginSettings() {}
|
||||
|
||||
};
|
@ -23,6 +23,10 @@ protected:
|
||||
UPROPERTY(EditAnywhere)
|
||||
FName ActionOrAxisName;
|
||||
|
||||
/// If binding type is EnhancedInputAction, a reference to an enhanced input action
|
||||
UPROPERTY(EditAnywhere) // can't be inside #if
|
||||
TSoftObjectPtr<UInputAction> InputAction;
|
||||
|
||||
/// Where there are multiple mappings, which to prefer
|
||||
UPROPERTY(EditAnywhere)
|
||||
EInputImageDevicePreference DevicePreference = EInputImageDevicePreference::Auto;
|
||||
@ -42,6 +46,8 @@ protected:
|
||||
bool bSubbedToInputEvents = false;
|
||||
bool bIsDirty = true;
|
||||
float DelayUpdate = 0;
|
||||
bool bHiddenBecauseBlank;
|
||||
ESlateVisibility OldVisibility;
|
||||
|
||||
public:
|
||||
|
||||
@ -57,6 +63,10 @@ public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void SetFromKey(FKey K);
|
||||
|
||||
/// Tell this image to display Enhanced InputAction
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void SetFromInputAction(UInputAction* Action);
|
||||
|
||||
/// Get the binding type that we'll use to populate the image
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual EInputBindingType GetBindingType() const { return BindingType; }
|
||||
@ -96,5 +106,7 @@ protected:
|
||||
|
||||
UFUNCTION()
|
||||
void OnInputModeChanged(int ChangedPlayerIdx, EInputMode InputMode);
|
||||
UFUNCTION()
|
||||
void OnEnhancedInputMappingsChanged();
|
||||
|
||||
};
|
||||
|
@ -25,10 +25,11 @@ public class StevesUEHelpers : ModuleRules
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"InputCore",
|
||||
"EnhancedInput",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"UMG",
|
||||
"Paper2D"
|
||||
"Paper2D",
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -17,10 +17,15 @@ InputImage requires a [UiTheme](UiTheme.md) to operate, which links to the image
|
||||
### Binding Type
|
||||
|
||||
|
||||
* "Action" if the image should display the current mapping for an input action
|
||||
* "Axis" to look up an input axis
|
||||
* "Enhanced Input Action" to specify an [Enhanced Input](https://docs.unrealengine.com/5.1/en-US/enhanced-input-in-unreal-engine/) action
|
||||
* "Action" if the image should display the current mapping for a legacy input action
|
||||
* "Axis" to look up a legacy input axis
|
||||
* "Key" to manually specify a key (which can be gamepad or mouse too)
|
||||
|
||||
### Enhanced Input Action
|
||||
|
||||
Pick an Enhanced Input action from the asset browser interface.
|
||||
|
||||
### Action or Axis Name
|
||||
|
||||
The name of the input action or axis that should be looked up to determine the
|
||||
|
@ -33,13 +33,21 @@ related to input controls. There are various options:
|
||||
|
||||
## Adding input images to rich text
|
||||
|
||||
### Input Actions
|
||||
### Enhanced Input Actions
|
||||
|
||||
`<input eaction="IA_MyAction"/>`
|
||||
|
||||
This displays the image for a bound Enhanced Input action. The name of the action
|
||||
should match the action name, which is relative to one of the directories
|
||||
you specify in Project Settings > Plugins > StevesUEHelpers.
|
||||
|
||||
### Legacy Input Actions
|
||||
|
||||
`<input action="TheActionName"/>`
|
||||
|
||||
This displays the image for a bound action input, as configured in project settings.
|
||||
|
||||
### Input Axes
|
||||
### Legacy Input Axes
|
||||
|
||||
`<input axis="TheAxisName"/>`
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user