WB_Hotkeys redesigned to use enhanced input. Amazing!

This commit is contained in:
2026-04-17 02:18:30 -04:00
parent 26399a6a15
commit ae1ad7640d
10 changed files with 169 additions and 11 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,84 @@
#include "LuprexUserWidget.h"
#include "EnhancedInputComponent.h"
#include "InputAction.h"
UlxUserWidget::UlxUserWidget(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UlxUserWidget::NativeOnInitialized()
{
Super::NativeOnInitialized();
BackupInputComponent();
}
void UlxUserWidget::BackupInputComponent()
{
SavedEnhancedActionEventBindings.Reset();
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent);
if (!EIC) return;
const TArray<EventBinding>& Live = EIC->GetActionEventBindings();
SavedEnhancedActionEventBindings.Reserve(Live.Num());
for (const EventBinding& Binding : Live)
{
SavedEnhancedActionEventBindings.Add(Binding->Clone());
}
}
void UlxUserWidget::DisableEventBinding(const UInputAction* InputAction)
{
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent);
if (!EIC) return;
TArray<EventBinding>& Bindings = GetMutableActionEventBindings(EIC);
Bindings.RemoveAll([InputAction](const EventBinding& B)
{
return B->GetAction() == InputAction;
});
}
void UlxUserWidget::RestoreInputBinding(const UInputAction* InputAction)
{
DisableEventBinding(InputAction);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent);
if (!EIC) return;
TArray<EventBinding>& Live = GetMutableActionEventBindings(EIC);
for (const EventBinding& Saved : SavedEnhancedActionEventBindings)
{
if (Saved->GetAction() == InputAction)
{
Live.Add(Saved->Clone());
}
}
}
void UlxUserWidget::RedirectInputAction(const UInputAction* From, const UInputAction* To)
{
DisableEventBinding(From);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent);
if (!EIC) return;
for (const EventBinding& Saved : SavedEnhancedActionEventBindings)
{
if (Saved->GetAction() == To)
{
TSharedPtr<FEnhancedInputActionEventBinding> Clone(Saved->Clone().Release());
EIC->BindActionInstanceLambda(From, Saved->GetTriggerEvent(),
[Clone](const FInputActionInstance& Data)
{
Clone->Execute(Data);
});
}
}
}
TArray<UlxUserWidget::EventBinding>& UlxUserWidget::GetMutableActionEventBindings(UEnhancedInputComponent* EIC)
{
return const_cast<TArray<EventBinding>&>(EIC->GetActionEventBindings());
}

View File

@@ -0,0 +1,50 @@
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "EnhancedInputComponent.h"
#include "LuprexUserWidget.generated.h"
UCLASS(BlueprintType, Blueprintable)
class INTEGRATION_API UlxUserWidget : public UUserWidget
{
GENERATED_BODY()
public:
using EventBinding = TUniquePtr<FEnhancedInputActionEventBinding>;
UlxUserWidget(const FObjectInitializer& ObjectInitializer);
virtual void NativeOnInitialized() override;
// Clone every enhanced-input action binding currently on InputComponent
// into SavedEnhancedActionEventBindings, so bindings can later be removed
// from the component and reinstated without losing their delegates.
void BackupInputComponent();
// Remove every live event binding whose action is InputAction.
// No-op if there are none, or if InputComponent isn't enhanced.
UFUNCTION(BlueprintCallable, Category="Luprex|Widget Enhanced Input")
void DisableEventBinding(const UInputAction* InputAction);
// Replace any live bindings for InputAction with fresh clones of every
// saved binding for that action. Leaves the backup array intact so this
// can be called repeatedly.
UFUNCTION(BlueprintCallable, Category="Luprex|Widget Enhanced Input")
void RestoreInputBinding(const UInputAction* InputAction);
// Install live bindings on From that, when fired, dispatch through a
// clone of each saved binding for To. Clears any pre-existing live
// bindings on From first. Backup array is untouched.
UFUNCTION(BlueprintCallable, Category="Luprex|Widget Enhanced Input")
void RedirectInputAction(const UInputAction* From, const UInputAction* To);
// Cloned bindings captured from InputComponent after construction.
TArray<EventBinding> SavedEnhancedActionEventBindings;
private:
// Strip the synthetic const off UEnhancedInputComponent::GetActionEventBindings
// to get direct mutable access to the protected array. Well-defined because
// the underlying object is not const; only the getter's return type is.
static TArray<EventBinding>& GetMutableActionEventBindings(UEnhancedInputComponent* EIC);
};

View File

@@ -243,6 +243,20 @@ FKey UlxUtilityLibrary::GetKeyByNameString(const FString &Name)
return Key.IsValid() ? Key : FKey(); return Key.IsValid() ? Key : FKey();
} }
UInputAction *UlxUtilityLibrary::FindInputActionByName(const UInputMappingContext *MappingContext, const FString &Name)
{
if (!MappingContext) return nullptr;
FName Target(*Name);
for (const FEnhancedActionKeyMapping &Mapping : MappingContext->GetMappings())
{
if (Mapping.Action && Mapping.Action->GetFName() == Target)
{
return const_cast<UInputAction *>(Mapping.Action.Get());
}
}
return nullptr;
}
FVector UlxUtilityLibrary::GetActorForwardVelocity(const AActor *Actor, double Speed, bool bSnapToXY) FVector UlxUtilityLibrary::GetActorForwardVelocity(const AActor *Actor, double Speed, bool bSnapToXY)
{ {
if (!Actor) return FVector::ZeroVector; if (!Actor) return FVector::ZeroVector;

View File

@@ -159,6 +159,13 @@ public:
UFUNCTION(BlueprintPure, Category = "Input|Key") UFUNCTION(BlueprintPure, Category = "Input|Key")
static FKey GetKeyByNameString(const FString &Name); static FKey GetKeyByNameString(const FString &Name);
// Find an InputAction within an InputMappingContext, matched by asset
// name (e.g. "IA_Jump"). Returns nullptr if the mapping context is
// null or no action with the given name is mapped.
//
UFUNCTION(BlueprintPure, Category = "Input")
static UInputAction *FindInputActionByName(const UInputMappingContext *MappingContext, const FString &Name);
// Get the actor's forward vector multiplied by a speed. // Get the actor's forward vector multiplied by a speed.
// If SnapToXY is true, the forward vector is projected // If SnapToXY is true, the forward vector is projected
// onto the XY plane and renormalized before scaling. // onto the XY plane and renormalized before scaling.

View File

@@ -40,9 +40,9 @@ function cube.lookmenu(add)
end end
function sphere.lookhotkeys(add) function sphere.lookhotkeys(add)
add("Z", "Sphere Hi", function () dprint("Doing Sphere Hi") end) add("DPadU", "Sphere Hi", function () dprint("Doing Sphere Hi") end)
add("X", "Sphere Bye", function () dprint("Doing Sphere Bye") end) add("DPadL", "Sphere Bye", function () dprint("Doing Sphere Bye") end)
add("C", "Sphere Yo", function () dprint("Doing Sphere Yo") end) add("DPadR", "Sphere Yo", function () dprint("Doing Sphere Yo") end)
end end