// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Engine/EngineTypes.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "MovementComponentState.generated.h" ////////////////////////////////////////////////////////////// // // Very often, the animation blueprint of a character will // want to know the state of the character movement // component, including such things as Velocity, // Acceleration, IsFalling, etc. However, the movement // component cannot be accessed directly from the // animation graph, since it runs on a worker thread. // By copying the data into this plain struct, the // animation graph can safely read it. // ////////////////////////////////////////////////////////////// USTRUCT(BlueprintType) struct INTEGRATION_API FlxMovementComponentState { GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") FVector Velocity = FVector::ZeroVector; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") bool bIsAccelerating = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") float MaxWalkSpeed = 0.0f; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") TEnumAsByte MovementMode = MOVE_None; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") bool bIsFalling = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Luprex|Movement Component State") bool bIsCrouching = false; FlxMovementComponentState() = default; explicit FlxMovementComponentState(class UCharacterMovementComponent *CMC); }; UCLASS() class INTEGRATION_API UlxMovementComponentStateLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: /////////////////////////////////////////////////////////// // // True field getters. // /////////////////////////////////////////////////////////// UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static FVector GetVelocity(const FlxMovementComponentState &State) { return State.Velocity; } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static bool GetIsAccelerating(const FlxMovementComponentState &State) { return State.bIsAccelerating; } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static float GetMaxWalkSpeed(const FlxMovementComponentState &State) { return State.MaxWalkSpeed; } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static EMovementMode GetMovementMode(const FlxMovementComponentState &State) { return State.MovementMode; } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static bool GetIsFalling(const FlxMovementComponentState &State) { return State.bIsFalling; } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static bool GetIsCrouching(const FlxMovementComponentState &State) { return State.bIsCrouching; } /////////////////////////////////////////////////////////// // // These are not true getters, but actually calculate // simple values from the existing fields. // /////////////////////////////////////////////////////////// UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static float GetGroundSpeed(const FlxMovementComponentState &State) { return State.Velocity.Size2D(); } UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State", meta = (BlueprintThreadSafe)) static bool GetShouldMove(const FlxMovementComponentState &State); /////////////////////////////////////////////////////////// // // Debugging. // /////////////////////////////////////////////////////////// UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Movement Component State") static FString DebugString(const FlxMovementComponentState &State); // Allows you to pass a MovementComponentState to Format Message. // UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Movement Component State") static FFormatArgumentData FormatArgumentDataMovementComponentState(const FlxMovementComponentState &AutoConvertedValue, const FString &Name); /////////////////////////////////////////////////////////// // // Other operations. // /////////////////////////////////////////////////////////// // Get a snapshot the Movement Component State. // // Normally, this just pulls data directly from the // character movement component. However, we sometimes // need to disable the movement component, especially // during cutscenes. We provide an alternative 'Fake // Movement Component State' stored on the actor's // UlxTangible. When the movement component's mode is // MOVE_None, this function returns the fake movement // component state instead. The fake movement component // state can be updated manually in blueprints. // UFUNCTION(BlueprintCallable, Category = "Luprex|Movement Component State", meta = (DefaultToSelf = "AnimInstance")) static FlxMovementComponentState GetMovementComponentState(UAnimInstance *AnimInstance); // Update the fake movement component state stored on // the actor's tangible. The fake movement component // state is usually read by the animation blueprint // when the real movement component is disabled. // UFUNCTION(BlueprintCallable, Category = "Luprex|Movement Component State", meta = (DefaultToSelf = "Actor", AutoCreateRefTerm = "State")) static FlxMovementComponentState SetFakeMovementComponentState(AActor *Actor, const FlxMovementComponentState &State); };