跳转至

Make Enhanced Input Trriger Support "hold"

In the last post, I mentioned that the CommonUI Enhanced Input Trigger does not support the "Hold" action. Here is my solution: create a class derived from "CommonBaseButton" to make the Enhanced Input Trigger support the "Hold" action without modifying the UE source code.


HoldSupportBaseButton.h

#pragma once

#include "CoreMinimal.h"
#include "CommonButtonBase.h"
#include "HoldSupportBaseButton.generated.h"

class FHoldEventDelegate;
/**
 *  Enhanced Input trigger Hold support button
 */
UCLASS()
class AURA_API UHoldSupportBaseButton : public UCommonButtonBase
{
    GENERATED_BODY()

protected:
    virtual void NativeConstruct() override;

    UFUNCTION()
    void EnhancedHoldProgress(float HoldProgress);

public:

    UFUNCTION(BlueprintImplementableEvent, Category = "Aura|UI")
    void OnHoldComplete();

    UFUNCTION()
    void CheckAndAddHoldBinding();

    FDelegateHandle HoldSupportHandle;
};

HoldSupportBaseButton.cpp

#include "UI/Widget/HoldSupportBaseButton.h"
#include "EnhancedActionKeyMapping.h"
#include "EnhancedInputSubsystems.h"
#include "ICommonInputModule.h"
#include "Input/UIActionBinding.h"
#include "UI/Widget/AuraActivatableWidget.h"

void UHoldSupportBaseButton::NativeConstruct()
{
    Super::NativeConstruct();
    CheckAndAddHoldBinding();

    if (GetOwningLocalPlayer())
    {
        UEnhancedInputLocalPlayerSubsystem* EnhancedInputSubsystem = GetOwningLocalPlayer()->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>();
        if (EnhancedInputSubsystem)
        {
            // make sure FEnhancedActionKeyMapping is set up correctly
            EnhancedInputSubsystem->ControlMappingsRebuiltDelegate.AddUniqueDynamic(this, &UHoldSupportBaseButton::CheckAndAddHoldBinding);
        }
    }

}

/*
 * I don't want to use bRequiresHold for EnhancedInputAction, I want to use the mapping to determine if it requires hold,
 * the bRequiresHold is for Button itself not for a speacific EnhancedInputAction
 * if a EnhancedInputAction has a hold mapping, then it requires hold.
 * 
 */
void UHoldSupportBaseButton::CheckAndAddHoldBinding()
{
    // if (!bRequiresHold) return;
    if (!TriggeringEnhancedInputAction) return;
    if (!TriggeringBindingHandle.IsValid()) return;
    const TSharedPtr<FUIActionBinding> ActionBinding = FUIActionBinding::FindBinding(TriggeringBindingHandle);
    if (!ActionBinding.IsValid()) return ;
    // ActionBinding->OnHoldActionPressed.AddUObject(this, &UHoldSupportBaseButton::NativeOnPressed);
    ActionBinding->OnHoldActionProgressed.Remove(HoldSupportHandle);

    HoldSupportHandle = ActionBinding->OnHoldActionProgressed.AddUObject(this,&UHoldSupportBaseButton::EnhancedHoldProgress);
    if (const UEnhancedInputLocalPlayerSubsystem* InputSystem = GetOwningLocalPlayer()->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
    {
        for (const FEnhancedActionKeyMapping& Mapping : InputSystem->GetAllPlayerMappableActionKeyMappings())
        {
            if (Mapping.Action == TriggeringEnhancedInputAction)
            {
                UInputTriggerHold* Trigger = nullptr;
                Mapping.Action->Triggers.FindItemByClass(&Trigger);
                if (Trigger)
                {
                    FUIActionKeyMapping KeyMapping(Mapping.Key, Trigger->HoldTimeThreshold, Trigger->HoldTimeThreshold);
                    ActionBinding->HoldMappings.Add(KeyMapping);
                }
                else  if (HoldData && bRequiresHold)
                {
                    const UCommonUIHoldData* CommonUIHoldBehaviorValues =HoldData.GetDefaultObject();
                    FUIActionKeyMapping KeyMapping(Mapping.Key, CommonUIHoldBehaviorValues->KeyboardAndMouse.HoldTime, CommonUIHoldBehaviorValues->KeyboardAndMouse.HoldRollbackTime);
                    ActionBinding->HoldMappings.Add(KeyMapping);
                }
            }
        }
    }
}



void UHoldSupportBaseButton::EnhancedHoldProgress(const float HoldProgress)
{
    if (HoldProgress >= 1.0f)
    {
        OnHoldComplete();
    }
}

评论