Files
2026-03-03 01:23:02 +08:00

164 lines
5.6 KiB
C++

// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GMS_Vector.generated.h"
UCLASS(Meta = (BlueprintThreadSafe))
class GENERICMOVEMENTSYSTEM_API UGMS_Vector : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
static FVector ClampMagnitude01(const FVector& Vector);
static FVector3f ClampMagnitude01(const FVector3f& Vector);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Clamp Magnitude 01 2D",
Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
static FVector2D ClampMagnitude012D(const FVector2D& Vector);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
static FVector2D RadianToDirection(float Radian);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
static FVector RadianToDirectionXY(float Radian);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
static FVector2D AngleToDirection(float Angle);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
static FVector AngleToDirectionXY(float Angle);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Direction", ReturnDisplayName = "Angle"))
static double DirectionToAngle(const FVector2D& Direction);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Direction", ReturnDisplayName = "Angle"))
static double DirectionToAngleXY(const FVector& Direction);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
static FVector PerpendicularClockwiseXY(const FVector& Vector);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
static FVector PerpendicularCounterClockwiseXY(const FVector& Vector);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Angle Between (Skip Normalization)",
Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Angle"))
static double AngleBetweenSkipNormalization(const FVector& From, const FVector& To);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Angle"))
static float AngleBetweenSignedXY(const FVector3f& From, const FVector3f& To);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Slerp (Skip Normalization)",
Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Direction"))
static FVector SlerpSkipNormalization(const FVector& From, const FVector& To, float Ratio);
};
inline FVector UGMS_Vector::ClampMagnitude01(const FVector& Vector)
{
const auto MagnitudeSquared{Vector.SizeSquared()};
if (MagnitudeSquared <= 1.0f)
{
return Vector;
}
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
return {Vector.X * Scale, Vector.Y * Scale, Vector.Z * Scale};
}
inline FVector3f UGMS_Vector::ClampMagnitude01(const FVector3f& Vector)
{
const auto MagnitudeSquared{Vector.SizeSquared()};
if (MagnitudeSquared <= 1.0f)
{
return Vector;
}
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
return {Vector.X * Scale, Vector.Y * Scale, Vector.Z * Scale};
}
inline FVector2D UGMS_Vector::ClampMagnitude012D(const FVector2D& Vector)
{
const auto MagnitudeSquared{Vector.SizeSquared()};
if (MagnitudeSquared <= 1.0f)
{
return Vector;
}
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
return {Vector.X * Scale, Vector.Y * Scale};
}
inline FVector2D UGMS_Vector::RadianToDirection(const float Radian)
{
float Sin, Cos;
FMath::SinCos(&Sin, &Cos, Radian);
return {Cos, Sin};
}
inline FVector UGMS_Vector::RadianToDirectionXY(const float Radian)
{
float Sin, Cos;
FMath::SinCos(&Sin, &Cos, Radian);
return {Cos, Sin, 0.0f};
}
inline FVector2D UGMS_Vector::AngleToDirection(const float Angle)
{
return RadianToDirection(FMath::DegreesToRadians(Angle));
}
inline FVector UGMS_Vector::AngleToDirectionXY(const float Angle)
{
return RadianToDirectionXY(FMath::DegreesToRadians(Angle));
}
inline double UGMS_Vector::DirectionToAngle(const FVector2D& Direction)
{
return FMath::RadiansToDegrees(FMath::Atan2(Direction.Y, Direction.X));
}
inline double UGMS_Vector::DirectionToAngleXY(const FVector& Direction)
{
return FMath::RadiansToDegrees(FMath::Atan2(Direction.Y, Direction.X));
}
inline FVector UGMS_Vector::PerpendicularClockwiseXY(const FVector& Vector)
{
return {Vector.Y, -Vector.X, Vector.Z};
}
inline FVector UGMS_Vector::PerpendicularCounterClockwiseXY(const FVector& Vector)
{
return {-Vector.Y, Vector.X, Vector.Z};
}
inline double UGMS_Vector::AngleBetweenSkipNormalization(const FVector& From, const FVector& To)
{
return FMath::RadiansToDegrees(FMath::Acos(From | To));
}
inline float UGMS_Vector::AngleBetweenSignedXY(const FVector3f& From, const FVector3f& To)
{
FVector2f FromXY{From};
FromXY.Normalize();
FVector2f ToXY{To};
ToXY.Normalize();
// return FMath::RadiansToDegrees(FMath::Atan2(FromXY ^ ToXY, FromXY | ToXY));
return FMath::RadiansToDegrees(FMath::Acos(FromXY | ToXY)) * FMath::Sign(FromXY ^ ToXY);
}