// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #pragma once #include "CoreMinimal.h" #include "Animation/AnimInstance.h" #include "Data/OLSEnumLibrary.h" #include "Kismet/KismetMathLibrary.h" #include "Data/OLSAnimationData.h" #include "Data/OLSLocomotionData.h" #include "OLSBaseLayerAnimInstance.generated.h" #if ENABLE_ANIM_DEBUG && ENABLE_VISUAL_LOG #define ENABLE_LOCOMOTION_DEBUG 1 #else #define ENABLE_LOCOMOTION_DEBUG 0 #endif /** * */ UCLASS() class OLSANIMATION_API UOLSBaseLayerAnimInstance : public UAnimInstance { GENERATED_BODY() public: UOLSBaseLayerAnimInstance(const FObjectInitializer& objectInitializer); protected: //~ Begin UAnimInstance overrides virtual void NativeInitializeAnimation() override; virtual void NativeUninitializeAnimation() override; virtual void NativeBeginPlay() override; virtual void NativeUpdateAnimation(float deltaSeconds) override; virtual void NativeThreadSafeUpdateAnimation(float deltaSeconds) override; virtual void NativePostEvaluateAnimation() override; //~ End UAnimInstance overrides protected: //~ Native update functions. virtual void NativeUpdateRotationData(class APawn* owningPawn, const float deltaSeconds); virtual void NativeUpdateLocationData(class APawn* owningPawn, const float deltaSeconds); virtual void NativeUpdateVelocityData(const TScriptInterface& moveableInterface, class APawn* owningPawn, const float deltaSeconds); virtual void NativeUpdateAccelerationData(class APawn* owningPawn, const float deltaSeconds); virtual void NativeUpdateCharacterStateData(const TScriptInterface& moveableInterface, class UPawnMovementComponent* movementComponent, const float deltaSeconds); virtual void NativeUpdateAimingData(class APawn* owningPawn, const float deltaSeconds); protected: //~ Native thread-safe update functions. virtual void NativeThreadSafeUpdateRotationData(const float deltaSeconds); virtual void NativeThreadSafeUpdateLocationData(const float deltaSeconds); virtual void NativeThreadSafeUpdateVelocityData(const float deltaSeconds); virtual void NativeThreadSafeUpdateAccelerationData(const float deltaSeconds); virtual void NativeThreadSafeUpdateWallDetectionHeuristic(const float deltaSeconds); virtual void NativeThreadSafeUpdateCharacterStateData(const float deltaSeconds); virtual void NativeThreadSafeUpdateAimingData(const float deltaSeconds); virtual void NativeThreadSafeUpdateRootYawOffset(const float deltaSeconds); protected: //~ Blueprint thread-safe implementable functions. UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateRotationData(float deltaSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateLocationData(float deltaSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateVelocityData(float deltaSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateAccelerationData(float deltaSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateWallDetectionHeuristic(const float deltaSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateCharacterData(float detalSeconds); UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (BlueprintThreadSafe)) void BlueprintThreadSafeUpdateAimingData(float deltaSeconds); public: UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) class UPawnMovementComponent* GetMovementComponent() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const FVector& GetWorldVelocity() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const float& GetLocalVelocityDirectionAngle() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const float& GetDisplacementSpeed() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const FVector& GetLocalAcceleration2D() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsLookingOrAimingDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsVelocityOrLookingDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsVelocityOrAimingDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsAimingDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsLookingDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsVelocityDirection() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsCrouching() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool HasVelocity() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool HasAcceleration() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool ShouldDistanceMatchStop() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) bool IsMovingPerpendicularToInitialPivot() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const EOLSRotationMode& GetRotationMode() const; UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) const float& GetOwningPawnMaxSpeed() const; protected: UFUNCTION(BlueprintCallable) void SetRootYawOffset(const float rootYawOffset); UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) void ProcessTurnYawCurve(); UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe)) void ProcessTurnYawCurve_ForwardFacing(); protected: UFUNCTION(BlueprintCallable, Category = "Masking", meta = (BlueprintThreadSafe)) float CalculateMeshSpaceBlendWeight(const FName localSpaceLayerCurveName) const; protected: UFUNCTION(BlueprintCallable, Category = "Components", meta = (BlueprintThreadSafe)) class UOLSLocomotionComponent* ThreadSafeGetLocomotionComponent() const; protected: UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|LocationData") FVector OwningPawnLocation = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|RotationData") FRotator OwningPawnRotation = FRotator::ZeroRotator; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|VelocityData") FVector OwningPawnVelocity = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|AccelerationData") FVector OwningPawnAcceleration = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") float OwningPawnGravityZ = 0.f; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") float OwningPawnMaxSpeed = 0.f; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") TEnumAsByte OwningPawnMovementMode = MOVE_None; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") uint8 bIsOwningPawnOnGround : 1 = false; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") uint8 bIsOwningPawnCrouching : 1 = false; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|CharacterStateData") uint8 bIsOwningOrientRotationToMovement : 1 = false; UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|AimingData") FRotator OwningPawnAimRotation = FRotator::ZeroRotator; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|RotationData") FRotator WorldRotation = FRotator::ZeroRotator; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|RotationData") float YawDeltaSinceLastUpdate = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|RotationData") float AdditiveLeanAngle = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|RotationData") float YawDeltaSpeed = 0.f; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|LocationData") FVector WorldLocation = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|LocationData") float DisplacementSinceLastUpdate = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|LocationData") float DisplacementSpeed = 0.f; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") FVector WorldVelocity = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") FVector LocalVelocity2D = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") float LocalVelocityDirectionAngle = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") float LocalVelocityDirectionAngleWithOffset = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") EOLSCardinalDirection LocalVelocityDirection = EOLSCardinalDirection::EForward; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") EOLSCardinalDirection LocalVelocityDirectionNoOffset = EOLSCardinalDirection::EForward; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") uint8 bHasVelocity : 1; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData") FVector LocalAcceleration2D = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData") uint8 bHasAcceleration : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData") FVector PivotDirection2D = FVector::ZeroVector; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData") EOLSCardinalDirection CardinalDirectionFromAcceleration = EOLSCardinalDirection::EForward; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bIsCrouching : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bHasCrouchStateChanged : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bHasADSStateChanged : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bWasADSLastUpdate : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") float TimeSinceFiredWeapon = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bIsJumping : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bIsFalling : 1; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") float TimeToJumpApex = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|CharacterStateData") uint8 bIsRunningIntoWall : 1; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|TurnInPlaceData") float RootYawOffset = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|TurnInPlaceData") FFloatSpringState RootYawOffsetSpringState; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|TurnInPlaceData") EOLSRootYawOffsetMode RootYawOffsetMode = EOLSRootYawOffsetMode::EBlendOut; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|TurnInPlaceData") float TurnYawCurveValue = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|TurnInPlaceData") float TurnInPlaceRotationDirection = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|TurnInPlaceData") float TurnInPlaceRecoveryDirection = 0.f; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|TurnInPlaceData") float MaxTurnYawValue = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|TurnInPlaceData") float CachedTurnYawCurveValue = 0.f; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|TurnInPlaceData") uint8 bHasReachedEndTurn : 1 = false; protected: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ThreadSafe|GameplayTagBindings") bool bGameplayTag_IsADS = false; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ThreadSafe|GameplayTagBindings") bool bGameplayTag_IsFiring = false; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ThreadSafe|GameplayTagBindings") bool bGameplayTag_IsDodging = false; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ThreadSafe|GameplayTagBindings") bool bGameplayTag_IsMeleeAttack = false; protected: UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AimingData") float AimPitch = 0.f; UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AimingData") float AimYaw = 0.f; protected: UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") float PivotInitialVelocityDirection = 0.f; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSCardinalDirection PivotInitialDirection = EOLSCardinalDirection::EForward; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") float LastPivotTime = 0.f; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSCardinalDirection StartDirection = EOLSCardinalDirection::EForward; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSGait StopInitialGait = EOLSGait::EWalk; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSCardinalDirection StopLocalVelocityCardinalDirection = EOLSCardinalDirection::EForward; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") uint8 bHasGaitChanged : 1; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") uint8 bHasRotationModeChanged : 1; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") uint8 bHasLinkedLayerChanged : 1; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSGait LastGait = EOLSGait::EWalk; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") EOLSRotationMode LastRotationMode = EOLSRotationMode::EVelocityDirection; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") TObjectPtr LastLinkedLayer = nullptr; protected: UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionComponentData") EOLSGait DesiredGait = EOLSGait::EWalk; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionComponentData") EOLSGait Gait = EOLSGait::EWalk; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionComponentData") EOLSGait PrevGait = EOLSGait::EWalk; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionComponentData") EOLSStance Stance = EOLSStance::EStanding; UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionComponentData") EOLSRotationMode RotationMode = EOLSRotationMode::EVelocityDirection; protected: #if WITH_EDITORONLY_DATA UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|Debug") uint8 bEnableDebug : 1; #endif UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") uint8 bEnableRootYawOffset : 1 = true; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") FName TurnYawWeightCurveName = NAME_None; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") FName RemainingTurnYawCurveName = NAME_None; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") FOLSRootYawOffsetClamps RootYawOffsetClamps; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") FVector2D RootYawOffsetAngleClamp_Standing = FVector2D(-120.f, 100.f); UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|TurnInPlaceData") FVector2D RootYawOffsetAngleClamp_Crouching = FVector2D(-90.f, 80.f); UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|VelocityData") float CardinalDirectionDeadZone = 10.f; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings") FGameplayTag ADSGameplayTag = FGameplayTag::EmptyTag; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings") FGameplayTag FiringGameplayTag = FGameplayTag::EmptyTag; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings") FGameplayTag DodgingGameplayTag = FGameplayTag::EmptyTag; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings") FGameplayTag MeleeGameplayTag = FGameplayTag::EmptyTag; protected: UPROPERTY(BlueprintReadOnly) uint8 bIsFirstUpdate : 1 = true; protected: // References UPROPERTY(Transient, DuplicateTransient) TObjectPtr OwningPawn = nullptr; UPROPERTY(Transient, DuplicateTransient) TObjectPtr MovementComponent = nullptr; UPROPERTY(Transient, DuplicateTransient) TObjectPtr LocomotionComponent = nullptr; TScriptInterface MoveableInterface = nullptr; protected: FOLSRootYawOffsetClamp CurrentRootYawOffset; };