Input buffer changed from a subsystem to an extension of the input component.

This commit is contained in:
Jamie Greunbaum 2023-09-21 20:32:29 -04:00
parent 74411baaea
commit a4913db597
4 changed files with 55 additions and 69 deletions

View File

@ -3,9 +3,8 @@
#include "Components/ComboManagerComponent.h"
#include "ComboInputAssets.h"
#include "EnhancedInputComponent.h"
#include "InputBufferLocalPlayerSubsystem.h"
#include "Components/InputBufferComponent.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
@ -20,22 +19,6 @@ UComboManagerComponent::UComboManagerComponent()
PrimaryComponentTick.bCanEverTick = false;
}
void UComboManagerComponent::BeginPlay()
{
Super::BeginPlay();
// If this component's owner is the player character or controller, attach it to the subsystem.
APlayerController *PlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (this->GetOwner() == PlayerController)
{
UEnhancedInputComponent *InputComponent = Cast<UEnhancedInputComponent>(PlayerController->InputComponent);
checkf(InputComponent, TEXT("Discovered player input component is not of type %s."), *UEnhancedInputComponent::StaticClass()->GetName());
UInputBufferLocalPlayerSubsystem *InputBufferSubsystem = PlayerController->GetLocalPlayer()->GetSubsystem<UInputBufferLocalPlayerSubsystem>();
InputBufferSubsystem->AttachComboManager(this, InputComponent);
}
}
void UComboManagerComponent::HandleComboInput(const UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent)
{
@ -105,8 +88,10 @@ void UComboManagerComponent::ActivateComboAction(const UComboInputAsset *Input)
void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAsset> Unlock)
{
APlayerController *Controller = UGameplayStatics::GetPlayerController(this, 0);
UInputBufferLocalPlayerSubsystem *Subsystem = Controller->GetLocalPlayer()->GetSubsystem<UInputBufferLocalPlayerSubsystem>();
Subsystem->UnlockComboInput(Unlock);
if (UInputBufferComponent *InputComponent = Cast<UInputBufferComponent>(Controller->InputComponent))
{
InputComponent->UnlockComboInput(Unlock);
}
}
void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *Input)

View File

@ -1,45 +1,49 @@
// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
#include "InputBufferLocalPlayerSubsystem.h"
#include "Components/InputBufferComponent.h"
#include "ComboInputAssets.h"
#include "EnhancedInputComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Components/ComboManagerComponent.h"
#include "GlobalSettings/InputBufferSubsystemGlobalSettings.h"
DEFINE_LOG_CATEGORY(LogInputBufferLocalPlayerSubsystem);
DEFINE_LOG_CATEGORY(LogInputBufferComponent);
void UInputBufferLocalPlayerSubsystem::Initialize(FSubsystemCollectionBase &Collection)
void UInputBufferComponent::BeginPlay()
{
Super::Initialize(Collection);
}
Super::BeginPlay();
void UInputBufferLocalPlayerSubsystem::AttachComboManager(UComboManagerComponent *ComboManager, UEnhancedInputComponent *InputComponent)
{
// Get the player character and try to connect to its combo manager.
this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput);
// Get all unique EnhancedInput actions bound to combo input actions.
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
TSet<const UInputAction*> InputActionsToBind;
for (TSoftObjectPtr<const UComboInputAsset> ComboInput : Settings->ComboActions)
if (APlayerController *PlayerController = UGameplayStatics::GetPlayerController(this, 0))
{
for (const UInputAction *InputAction : ComboInput->ActionGroup)
if (UComboManagerComponent *ComboManager = PlayerController->GetComponentByClass<UComboManagerComponent>())
{
InputActionsToBind.Add(InputAction);
// Get the player character and try to connect to its combo manager.
this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput);
// Get all unique EnhancedInput actions bound to combo input actions.
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
TSet<const UInputAction *> InputActionsToBind;
for (TSoftObjectPtr<const UComboInputAsset> ComboInput : Settings->ComboActions)
{
for (const UInputAction *InputAction : ComboInput->ActionGroup)
{
InputActionsToBind.Add(InputAction);
}
}
for (const UInputAction *InputAction : InputActionsToBind)
{
this->BindAction(InputAction, ETriggerEvent::Started, this, &UInputBufferComponent::AddActionToBuffer, InputAction);
this->BindAction(InputAction, ETriggerEvent::Completed, this, &UInputBufferComponent::ExpireAction, InputAction);
}
}
}
for (const UInputAction *InputAction : InputActionsToBind)
{
InputComponent->BindAction(InputAction, ETriggerEvent::Started, this, &UInputBufferLocalPlayerSubsystem::AddActionToBuffer, InputAction);
InputComponent->BindAction(InputAction, ETriggerEvent::Completed, this, &UInputBufferLocalPlayerSubsystem::ExpireAction, InputAction);
}
}
void UInputBufferLocalPlayerSubsystem::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action)
void UInputBufferComponent::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action)
{
this->MostRecentActions.Add(Action);
this->ExpiringActions.Remove(Action);
@ -56,9 +60,9 @@ void UInputBufferLocalPlayerSubsystem::AddActionToBuffer(const FInputActionValue
}
}
this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ClearMultiPresses, Settings->MultiPressTimerLength);
this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferComponent::ClearMultiPresses, Settings->MultiPressTimerLength);
}
void UInputBufferLocalPlayerSubsystem::ClearMultiPresses()
void UInputBufferComponent::ClearMultiPresses()
{
#if WITH_EDITOR
TArray<FString> ActionNames;
@ -66,12 +70,12 @@ void UInputBufferLocalPlayerSubsystem::ClearMultiPresses()
{
ActionNames.Add(Action->GetName());
}
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
#endif
this->MostRecentActions.Empty();
}
void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset *ComboInput)
void UInputBufferComponent::ActivateComboInput(const UComboInputAsset *ComboInput)
{
checkf(ComboInput, TEXT("Invalid %s."), *UComboInputAsset::StaticClass()->GetName());
@ -101,7 +105,7 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
this->OnNewComboInput.Execute(ComboInput, EComboActionTriggerEvent::Released);
}
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is active."), *ComboInput->ComboInputName.ToString());
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s is active."), *ComboInput->ComboInputName.ToString());
}
else
{
@ -109,32 +113,32 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
}
}
void UInputBufferLocalPlayerSubsystem::HoldComboInput(const UComboInputAsset *ComboInput)
void UInputBufferComponent::HoldComboInput(const UComboInputAsset *ComboInput)
{
this->InputBufferHold = ComboInput;
UE_SUPPRESS(LogInputBufferLocalPlayerSubsystem, Verbose,
UE_SUPPRESS(LogInputBufferComponent, Verbose,
{
if (this->LockedComboInputs.Contains(ComboInput))
{
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is locked and won't be activated yet."), *ComboInput->ComboInputName.ToString());
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s is locked and won't be activated yet."), *ComboInput->ComboInputName.ToString());
}
else
{
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s added to buffer."), *ComboInput->ComboInputName.ToString());
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s added to buffer."), *ComboInput->ComboInputName.ToString());
}
}
);
}
void UInputBufferLocalPlayerSubsystem::LockComboInput(const UComboInputAsset *Input)
void UInputBufferComponent::LockComboInput(const UComboInputAsset *Input)
{
this->LockedComboInputs.Emplace(Input);
}
void UInputBufferLocalPlayerSubsystem::UnlockComboInput(const UComboInputAsset *Unlocked)
void UInputBufferComponent::UnlockComboInput(const UComboInputAsset *Unlocked)
{
// Remove the newly-unlocked asset from the locked combo inputs.
UE_CLOG(this->LockedComboInputs.Contains(Unlocked), LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has unlocked."), *Unlocked->ComboInputName.ToString());
UE_CLOG(this->LockedComboInputs.Contains(Unlocked), LogInputBufferComponent, Verbose, TEXT("%s has unlocked."), *Unlocked->ComboInputName.ToString());
this->LockedComboInputs.Remove(Unlocked);
// Check if the newly unlocked combo input is in the hold.
@ -150,11 +154,11 @@ void UInputBufferLocalPlayerSubsystem::UnlockComboInput(const UComboInputAsset *
this->ActivateComboInput(HeldAsset);
}
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has expired."), *OriginalActive->ComboInputName.ToString());
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s has expired."), *OriginalActive->ComboInputName.ToString());
}
}
void UInputBufferLocalPlayerSubsystem::ExpireAction(const FInputActionValue &Value, const class UInputAction *Action)
void UInputBufferComponent::ExpireAction(const FInputActionValue &Value, const class UInputAction *Action)
{
// Only send a release event if we haven't already, i.e. if the combo input associated
// with the action is not already buffered for another future activation.
@ -166,21 +170,21 @@ void UInputBufferLocalPlayerSubsystem::ExpireAction(const FInputActionValue &Val
// Prepare to expire any buffered combo inputs
this->ExpiringActions.Add(Action);
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferComponent::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
}
void UInputBufferLocalPlayerSubsystem::ExpireBufferedActions()
void UInputBufferComponent::ExpireBufferedActions()
{
// Only bother dealing with this if there's something to deal with in the first place.
if (!this->ExpiringActions.IsEmpty())
{
UE_SUPPRESS(LogInputBufferLocalPlayerSubsystem, Verbose,
UE_SUPPRESS(LogInputBufferComponent, Verbose,
{
TArray<FString> ActionNames;
for (const UInputAction *Action : this->ExpiringActions)
{
ActionNames.Add(Action->GetName());
}
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("Released actions expired (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Released actions expired (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
}
);
@ -192,7 +196,7 @@ void UInputBufferLocalPlayerSubsystem::ExpireBufferedActions()
{
if (this->InputBufferHold->MatchesInputAction(Action))
{
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has been cancelled."), *this->InputBufferHold->ComboInputName.ToString());
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s has been cancelled."), *this->InputBufferHold->ComboInputName.ToString());
this->InputBufferHold = nullptr;
break;
}

View File

@ -42,7 +42,6 @@ class COMBOINPUT_API UComboManagerComponent : public UActorComponent
public:
UComboManagerComponent();
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable)
void HandleComboInput(const class UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent);

View File

@ -3,11 +3,11 @@
#pragma once
#include "CoreMinimal.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "InputBufferLocalPlayerSubsystem.generated.h"
#include "InputBufferComponent.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogInputBufferLocalPlayerSubsystem, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogInputBufferComponent, Log, All);
DECLARE_DELEGATE_TwoParams(FNewComboInput, const class UComboInputAsset*, const EComboActionTriggerEvent &);
@ -16,14 +16,12 @@ DECLARE_DELEGATE_TwoParams(FNewComboInput, const class UComboInputAsset*, const
* Subsystem that handles input buffering, and passing the resulting actions to the player's ComboManagerComponent.
*/
UCLASS()
class COMBOINPUT_API UInputBufferLocalPlayerSubsystem : public UEnhancedInputLocalPlayerSubsystem
class COMBOINPUT_API UInputBufferComponent : public UEnhancedInputComponent
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase &Collection) override;
void AttachComboManager(class UComboManagerComponent *ComboManager, class UEnhancedInputComponent *InputComponent);
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable)
void LockComboInput(const class UComboInputAsset *Input);