From a4913db5973710a9fbe2d346abaae93d04f036fb Mon Sep 17 00:00:00 2001 From: Jamie Greunbaum Date: Thu, 21 Sep 2023 20:32:29 -0400 Subject: [PATCH] Input buffer changed from a subsystem to an extension of the input component. --- .../Components/ComboManagerComponent.cpp | 25 ++---- .../InputBufferComponent.cpp} | 86 ++++++++++--------- .../Public/Components/ComboManagerComponent.h | 1 - .../InputBufferComponent.h} | 12 ++- 4 files changed, 55 insertions(+), 69 deletions(-) rename Source/ComboInput/Private/{InputBufferLocalPlayerSubsystem.cpp => Components/InputBufferComponent.cpp} (56%) rename Source/ComboInput/Public/{InputBufferLocalPlayerSubsystem.h => Components/InputBufferComponent.h} (78%) diff --git a/Source/ComboInput/Private/Components/ComboManagerComponent.cpp b/Source/ComboInput/Private/Components/ComboManagerComponent.cpp index fe768e9..3fdce4c 100644 --- a/Source/ComboInput/Private/Components/ComboManagerComponent.cpp +++ b/Source/ComboInput/Private/Components/ComboManagerComponent.cpp @@ -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(PlayerController->InputComponent); - checkf(InputComponent, TEXT("Discovered player input component is not of type %s."), *UEnhancedInputComponent::StaticClass()->GetName()); - - UInputBufferLocalPlayerSubsystem *InputBufferSubsystem = PlayerController->GetLocalPlayer()->GetSubsystem(); - 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 Unlock) { APlayerController *Controller = UGameplayStatics::GetPlayerController(this, 0); - UInputBufferLocalPlayerSubsystem *Subsystem = Controller->GetLocalPlayer()->GetSubsystem(); - Subsystem->UnlockComboInput(Unlock); + if (UInputBufferComponent *InputComponent = Cast(Controller->InputComponent)) + { + InputComponent->UnlockComboInput(Unlock); + } } void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *Input) diff --git a/Source/ComboInput/Private/InputBufferLocalPlayerSubsystem.cpp b/Source/ComboInput/Private/Components/InputBufferComponent.cpp similarity index 56% rename from Source/ComboInput/Private/InputBufferLocalPlayerSubsystem.cpp rename to Source/ComboInput/Private/Components/InputBufferComponent.cpp index ee47ed9..a219e52 100644 --- a/Source/ComboInput/Private/InputBufferLocalPlayerSubsystem.cpp +++ b/Source/ComboInput/Private/Components/InputBufferComponent.cpp @@ -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(); - TSet InputActionsToBind; - for (TSoftObjectPtr ComboInput : Settings->ComboActions) + if (APlayerController *PlayerController = UGameplayStatics::GetPlayerController(this, 0)) { - for (const UInputAction *InputAction : ComboInput->ActionGroup) + if (UComboManagerComponent *ComboManager = PlayerController->GetComponentByClass()) { - 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(); + TSet InputActionsToBind; + for (TSoftObjectPtr 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 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(); - 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 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; } diff --git a/Source/ComboInput/Public/Components/ComboManagerComponent.h b/Source/ComboInput/Public/Components/ComboManagerComponent.h index b9458f4..cc5cf30 100644 --- a/Source/ComboInput/Public/Components/ComboManagerComponent.h +++ b/Source/ComboInput/Public/Components/ComboManagerComponent.h @@ -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); diff --git a/Source/ComboInput/Public/InputBufferLocalPlayerSubsystem.h b/Source/ComboInput/Public/Components/InputBufferComponent.h similarity index 78% rename from Source/ComboInput/Public/InputBufferLocalPlayerSubsystem.h rename to Source/ComboInput/Public/Components/InputBufferComponent.h index 8380991..4c386dc 100644 --- a/Source/ComboInput/Public/InputBufferLocalPlayerSubsystem.h +++ b/Source/ComboInput/Public/Components/InputBufferComponent.h @@ -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);