OLS/Source/OLSAnimation/Public/Libraries/OLSLocomotionBPLibrary.h

206 lines
14 KiB
C++

// © 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 "SequenceEvaluatorLibrary.h"
#include "Data/OLSAnimationData.h"
#include "Data/OLSEnumLibrary.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "OLSLocomotionBPLibrary.generated.h"
/**
*
*/
UCLASS()
class OLSANIMATION_API UOLSLocomotionBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public: // ~ Helpers ~ //
/**
* Finds the time within an animation sequence when a character's root motion changes direction, commonly known as a "pivot."
*
* @param animSequence Pointer to the animation sequence being analyzed. The function extracts root motion data from this sequence.
* @param sampleRate The frequency (in Hz) at which the animation is sampled. Higher values increase accuracy but may impact performance.
*
* @return The time (in seconds) within the animation sequence when a pivot occurs. Returns 0 if no pivot is detected or the input is invalid.
*
* @note This function is useful for identifying key moments in animations where directional changes occur,
* such as during character turns or sharp movements, ensuring smooth transitions or special handling.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static float FindPivotTime(const UAnimSequenceBase* animSequence, const float sampleRate);
/**
* Retrieves the value of a specified curve at a given time within an animation sequence.
*
* @param animSequence Pointer to the animation sequence containing the curve data.
* @param time The time (in seconds) at which to evaluate the curve value.
* @param curveName The name of the curve to evaluate.
*
* @return The curve value at the specified time. Returns 0 if the curve is invalid or the time is out of range.
*
* @note The time is clamped to ensure it falls within the animation's playback range, and the function requires at least 2 sampled keys in the animation for curve evaluation.
*/
static float GetCurveValueAtTime(const UAnimSequenceBase* animSequence, const float time, const FName& curveName);
/**
* Retrieves the time within an animation sequence at which a specified curve reaches a given value.
*
* @param animSequence Pointer to the animation sequence containing the curve data.
* @param curveValue The target value to locate within the curve.
* @param curveName The name of the curve being evaluated.
*
* @return The interpolated time at which the curve reaches the specified value. Returns 0 if the curve is invalid or the value cannot be found.
*
* @note This function uses binary search to efficiently locate the curve value and linearly interpolates between keyframes for precision.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static float GetTimeAtCurveValue(const UAnimSequenceBase* animSequence, const float& curveValue, FName curveName);
/**
* Calculates the range of values for a specified animation curve within an animation sequence.
*
* @param animSequence Pointer to the animation sequence containing the curve. This sequence provides the curve data.
* @param curveName The name of the curve whose value range is to be calculated.
*
* @return The difference between the first and last values of the specified curve. Returns 0 if the curve is invalid or has insufficient data.
*
* @note This function is useful for determining the total change in a curve over the duration of an animation,
* which can be critical for understanding motion characteristics or driving procedural animations.
*/
static float GetCurveValuesRange(const UAnimSequenceBase* animSequence, const FName& curveName);
public:
/**
* Advances the animation time from the current position to a new time, ensuring the root motion covers the specified distance traveled.
*
* @param animSequence Pointer to the animation sequence being evaluated. Contains the root motion and curve data.
* @param currentTime The current time within the animation sequence, serving as the starting point for advancement.
* @param distanceTraveled The desired distance to advance within the animation, calculated based on the root motion curve.
* @param curveName The name of the curve representing root motion distance in the animation sequence.
* @param shouldAllowLooping Specifies whether the animation should loop if the new time exceeds the sequence length.
*
* @return The new animation time after advancing the desired distance along the root motion curve.
*
* @note This function ensures that the visual progression of the animation matches the actual distance traveled,
* which is particularly useful for root motion-based locomotion systems.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static float GetTimeAfterDistanceTraveled(const UAnimSequenceBase* animSequence,
float currentTime,
float distanceTraveled,
FName curveName,
const bool shouldAllowLooping);
/**
* Advances the animation time based on the distance traveled, adjusting the play rate to synchronize the animation with movement.
*
* @param outDesiredPlayRate Output parameter that will contain the calculated play rate needed to match the distance traveled.
* @param updateContext Provides context for the current animation update, including delta time and other relevant information.
* @param sequenceEvaluator Reference to the sequence evaluator managing the current animation sequence.
* @param distanceTraveled The distance covered since the last frame. This value determines how much the animation time should advance.
* @param curveName The name of the curve used for distance matching. This curve defines how the animation corresponds to distance traveled.
* @param playRateClamp Optional parameter defining the minimum and maximum play rates. Clamps the effective play rate to prevent unrealistic values.
* Default value: FVector2D(0.75f, 1.25f).
*
* @return The updated sequence evaluator with the new animation state.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static FSequenceEvaluatorReference AdvanceTimeByDistanceMatching(float& outDesiredPlayRate,
const FAnimUpdateContext& updateContext,
const FSequenceEvaluatorReference& sequenceEvaluator,
const float distanceTraveled,
const FName curveName,
const FVector2D playRateClamp = FVector2D(0.75f, 1.25f));
/**
* Adjusts the playback time of an animation sequence to match a specified distance to a target.
*
* This function ensures that the animation sequence progresses or adjusts its time based on the distance to a target.
* It uses a distance curve to determine the appropriate time within the animation sequence that corresponds to the desired distance.
*
* @param updateContext The context for the current animation update, providing necessary time and state information.
* @param sequenceEvaluator A reference to the sequence evaluator, which controls and tracks the animation sequence being played.
* @param distanceToTarget The distance to the target that the animation should match.
* Typically, negative values indicate distance curves storing negative distance.
* @param shouldDistanceMatchStop If true, the distance matching stops once the character reaches the target or passes the threshold.
* @param stopDistanceThreshHold The distance threshold at which distance matching should stop.
* If the evaluated distance curve value exceeds this threshold, distance matching will halt.
* @param animEndTime The end time of the animation sequence. If greater than 0, the sequence will not advance past this time.
* @param curveName The name of the curve within the animation sequence that stores distance information.
* This curve is evaluated to determine the time corresponding to the distance to the target.
*
* @return An updated sequence evaluator reference, reflecting the adjusted or advanced animation time.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static FSequenceEvaluatorReference DistanceMatchToTarget(const FAnimUpdateContext& updateContext,
const FSequenceEvaluatorReference& sequenceEvaluator,
float distanceToTarget,
bool shouldDistanceMatchStop, float stopDistanceThreshHold,
float animEndTime,
FName curveName);
/**
* Set the play rate of the sequence player so that the speed of the animation matches in-game movement speed.
* While distance matching is commonly used for transition animations, cycle animations (walk, jog, etc) typically just adjust their play rate to match
* the in-game movement speed.
* This function assumes that the animation has a constant speed.
* @param sequencePlayer - The sequence player node to operate on.
* @param speedToMatch - The in-game movement speed to match. This is usually the current speed of the movement component.
* @param playRateClamp - A clamp on how much the animation's play rate can change to match the in-game movement speed. Set to (0,0) for no clamping.
*/
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static FSequencePlayerReference SetPlayRateToMatchSpeed(const FSequencePlayerReference& sequencePlayer,
float speedToMatch, FVector2D playRateClamp = FVector2D(0.75f, 1.25f));
/**
* Predict where the character will stop based on its current movement properties and parameters from the movement component.
* This uses prediction logic that is heavily tied to the UCharacterMovementComponent.
* Each parameter corresponds to a value from the UCharacterMovementComponent with the same name.
* Because this is a thread safe function, it's recommended to populate these fields via the Property Access system.
* @return The predicted stop position in local space to the character. The size of this vector will be the distance to the stop location.
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static FVector PredictGroundMovementStopLocation(const FVector& velocity, bool shouldUseSeparateBrakingFriction,
float brakingFriction, float groundFriction,
float brakingFrictionFactor, float brakingDecelerationWalking);
/**
* Predict where the character will change direction during a pivot based on its current movement properties and parameters from the movement component.
* This uses prediction logic that is heavily tied to the UCharacterMovementComponent.
* Each parameter corresponds to a value from the UCharacterMovementComponent with the same name.
* Because this is a thread safe function, it's recommended to populate these fields via the Property Access system.
* @return The predicted pivot position in local space to the character. The size of this vector will be the distance to the pivot.
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "OLS|Function Library", meta=(BlueprintThreadSafe))
static FVector PredictGroundMovementPivotLocation(const FVector& acceleration, const FVector& velocity,
float groundFriction);
// UFUNCTION(BlueprintCallable,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
// static float RotationMatching(const float deltaTime, const float interpSpeed, const float animRotAlpha,
// const FVector& acceleration, const float targetAngle, UPARAM(ref) FOLSRotationMatchingData& outRotationMatchingData,
// UPARAM(ref) float& outTargetRotationYaw);
public:
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSCardinalDirection SelectCardinalDirectionFromAngle(float angle, float deadZone, EOLSCardinalDirection currentDirection, bool useCurrentDirection = false);
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSCardinalDirection GetOppositeCardinalDirectional(EOLSCardinalDirection currentDirection);
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSHipDirection GetOppositeHipDirection(EOLSHipDirection currentHipDirection);
public:
UFUNCTION(BlueprintCallable, Category = "OLS|Function Library")
static void TryLinkAnimLayer(USkeletalMeshComponent* mesh, TSubclassOf<UAnimInstance> animClass, FName groupName, bool shouldUnlinkGroupIfInvalid);
};