RSAbilityInputConfig.h
Click a line number to link it. Shift-click to select a range.
| 1 | // Copyright (c) 2026 Reignance Studios. MIT License, see LICENSE. |
| 2 | |
| 3 | #pragma once |
| 4 | |
| 5 | #include "CoreMinimal.h" |
| 6 | #include "Engine/DataAsset.h" |
| 7 | #include "EnhancedInputComponent.h" |
| 8 | #include "GameplayTagContainer.h" |
| 9 | #include "RSAbilityInputConfig.generated.h" |
| 10 | |
| 11 | class UInputAction; |
| 12 | |
| 13 | USTRUCT(BlueprintType) |
| 14 | struct FRSAbilityInputBinding |
| 15 | { |
| 16 | GENERATED_BODY() |
| 17 | |
| 18 | UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") |
| 19 | TObjectPtr<const UInputAction> InputAction = nullptr; |
| 20 | |
| 21 | /** Abilities whose asset tags include this tag start on press, e.g. Ability.Dash. */ |
| 22 | UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input", meta = (Categories = "Ability")) |
| 23 | FGameplayTag AbilityTag; |
| 24 | }; |
| 25 | |
| 26 | /** |
| 27 | * Maps Enhanced Input actions to ability tags, so abilities are bound by tag instead of by |
| 28 | * input ID. Press activates matching abilities (or forwards the press to an active one), |
| 29 | * release forwards to WaitInputRelease. See URSAbilitySystemLibrary::PressAbilityInputByTag. |
| 30 | * |
| 31 | * In C++, from SetupPlayerInputComponent: |
| 32 | * |
| 33 | * InputConfig->BindAbilityActions(CastChecked<UEnhancedInputComponent>(PlayerInputComponent), |
| 34 | * this, &AMyCharacter::AbilityInputPressed, &AMyCharacter::AbilityInputReleased); |
| 35 | * |
| 36 | * void AMyCharacter::AbilityInputPressed(FGameplayTag Tag) { URSAbilitySystemLibrary::PressAbilityInputByTag(this, Tag); } |
| 37 | * void AMyCharacter::AbilityInputReleased(FGameplayTag Tag) { URSAbilitySystemLibrary::ReleaseAbilityInputByTag(this, Tag); } |
| 38 | * |
| 39 | * In Blueprint, call Press/Release Ability Input By Tag from the Started and Completed pins. |
| 40 | */ |
| 41 | UCLASS(BlueprintType, Const) |
| 42 | class RSGASHELPERS_API URSAbilityInputConfig : public UDataAsset |
| 43 | { |
| 44 | GENERATED_BODY() |
| 45 | |
| 46 | public: |
| 47 | UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input", meta = (TitleProperty = "AbilityTag")) |
| 48 | TArray<FRSAbilityInputBinding> AbilityInputs; |
| 49 | |
| 50 | /** The tag bound to an action, or an empty tag. */ |
| 51 | UFUNCTION(BlueprintPure, Category = "RS|GAS|Input") |
| 52 | FGameplayTag FindAbilityTagForAction(const UInputAction* InputAction) const; |
| 53 | |
| 54 | /** |
| 55 | * Binds every entry: Started calls Pressed(Tag), Completed and Canceled call Released(Tag). |
| 56 | * Started fires once per press, so a held key does not retrigger the ability every frame. |
| 57 | */ |
| 58 | template <class UserClass, typename PressedFunc, typename ReleasedFunc> |
| 59 | void BindAbilityActions(UEnhancedInputComponent* Input, UserClass* Object, PressedFunc Pressed, ReleasedFunc Released) const |
| 60 | { |
| 61 | check(Input); |
| 62 | for (const FRSAbilityInputBinding& Binding : AbilityInputs) |
| 63 | { |
| 64 | if (!Binding.InputAction || !Binding.AbilityTag.IsValid()) |
| 65 | { |
| 66 | continue; |
| 67 | } |
| 68 | Input->BindAction(Binding.InputAction, ETriggerEvent::Started, Object, Pressed, Binding.AbilityTag); |
| 69 | Input->BindAction(Binding.InputAction, ETriggerEvent::Completed, Object, Released, Binding.AbilityTag); |
| 70 | Input->BindAction(Binding.InputAction, ETriggerEvent::Canceled, Object, Released, Binding.AbilityTag); |
| 71 | } |
| 72 | } |
| 73 | }; |