ProjectM/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.cpp

425 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "GlobalUtilsLibrary.h"
#include "Algo/Transform.h"
#include "Misc/Paths.h"
#include "HAL/PlatformProcess.h"
#include "Kismet/KismetMathLibrary.h"
#include "Components/SkeletalMeshComponent.h"
#include "ProjectT/ProjectT.h"
#include "ProjectT/System/Core/Managers/DataDam.h"
#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h"
#include "ProjectT/System/Core/CoreGameInstance.h"
#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h"
#include "ProjectT/Data/Gen/GenerateStructLocalization.h"
#include "ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h"
bool UGlobalUtilsLibrary::IsValueInRange(const int32 Value, const int32 A, const int32 B, bool GreaterEqual, bool LessEqual)
{
bool G = GreaterEqual ? (Value >= A) : (Value > A);
bool L = LessEqual ? (Value <= B) : (Value < B);
return G && L;
}
UWorld* UGlobalUtilsLibrary::GetValidWorld(UObject* Object)
{
UWorld* World = Object->GetWorld();
NMT_CHECKF(World);
return World;
}
UDataDam* UGlobalUtilsLibrary::GetSharedDataDam(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
UDataDam* Ret = IGlobalObjectProvider::Execute_GetDataDam(GI);
NMT_CHECKF(Ret);
return Ret;
}
UStageManager* UGlobalUtilsLibrary::GetSharedLevelManager(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
UStageManager* Ret = IGlobalObjectProvider::Execute_GetStageManager(GI);
NMT_CHECKF(Ret);
return Ret;
}
UOptionManager* UGlobalUtilsLibrary::GetSharedOptionManager(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
UOptionManager* Ret = IGlobalObjectProvider::Execute_GetOptionManager(GI);
NMT_CHECKF(Ret);
return Ret;
}
USoundManager* UGlobalUtilsLibrary::GetSharedSoundManager(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
USoundManager* Ret = IGlobalObjectProvider::Execute_GetSoundManager(GI);
NMT_CHECKF(Ret);
return Ret;
}
UCoreCheatManager* UGlobalUtilsLibrary::GetSharedCoreCheatManager(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
UCoreCheatManager* Ret = IGlobalObjectProvider::Execute_GetCoreCheatManager(GI);
NMT_CHECKF(Ret);
return Ret;
}
UNotificationCenter* UGlobalUtilsLibrary::GetSharedNotificationCenter(UObject* Object)
{
NMT_CHECKF(Object);
UWorld* World = GetValidWorld(Object);
NMT_CHECKF(World);
UGameInstance* GI = UGameplayStatics::GetGameInstance(World);
NMT_CHECKF(GI);
UNotificationCenter* Ret = IGlobalObjectProvider::Execute_GetNotificationCenter(GI);
NMT_CHECKF(Ret);
return Ret;
}
bool UGlobalUtilsLibrary::IsStandalonePlay(UObject* Object)
{
NMT_CHECKF(Object);
ENetMode NetMode = Object->GetWorld()->GetNetMode();
return NetMode == NM_Standalone;
}
TArray<FString> UGlobalUtilsLibrary::ParseStringIndices(const TCHAR* Delimiter, const FString& Indices)
{
TArray<FString> Ret;
Indices.ParseIntoArray(Ret, TEXT(";"));
return Ret;
}
FString UGlobalUtilsLibrary::GetScriptTypeByRefPath(const FString& RefPath)
{
FString Ret;
if (RefPath.Split(TEXT("."), nullptr, &Ret))
Ret.Split(TEXT("'"), &Ret, nullptr);
return Ret;
}
EContentType UGlobalUtilsLibrary::GetContentTypeFromIndex(FName InRowName)
{
FString RowString = InRowName.ToString();
FString SliceString = DivideString(2, RowString);
int32 ContentTypeNumber = FCString::Atoi(*SliceString);
return StaticCast<EContentType>(ContentTypeNumber);
}
TArray<FString> UGlobalUtilsLibrary::ParseStringIndices(const FString& Indices, const FString& Delimeter)
{
TArray<FString> Ret;
Indices.ParseIntoArray(Ret, *Delimeter);
return Ret;
}
TArray<AActor*> UGlobalUtilsLibrary::GetFilteredCurrentActors(const TArray<AActor*>& InActors,
const TArray<UClass*>& IgnoreClasses, const TArray<UClass*>& IncludeClasses)
{
bool bActorSubclass = false;
bool bInterfaceClass = false;
for (UClass* Class : IgnoreClasses)
{
bActorSubclass = Class->IsChildOf(AActor::StaticClass());
bInterfaceClass = Class->IsChildOf(UInterface::StaticClass());
NMT_MSG_CHECKF(bActorSubclass || bInterfaceClass, "%s Contains a class that isnt allowed: %s", TEXT("IgnoreClasses"), *Class->GetName());
}
for (UClass* Class : IncludeClasses)
{
bActorSubclass = Class->IsChildOf(AActor::StaticClass());
bInterfaceClass = Class->IsChildOf(UInterface::StaticClass());
NMT_MSG_CHECKF(bActorSubclass || bInterfaceClass, "%s Contains a class that isnt allowed: %s", TEXT("IncludeClasses"), *Class->GetName());
}
TArray<TArray<AActor*>::ElementType> Ret = InActors.FilterByPredicate([&IgnoreClasses, &IncludeClasses](const AActor* Actor)
{
UClass* CurrentActorClass = Actor->GetClass();
if(IgnoreClasses.Contains(CurrentActorClass)) return false;
for(UClass* Class : IgnoreClasses)
{
if(Actor->IsA(Class)) return false;
if(CurrentActorClass->ImplementsInterface(Class)) return false;
}
if(IncludeClasses.Num() == 0) return true;
if(IncludeClasses.Contains(CurrentActorClass)) return true;
for(UClass* Class : IncludeClasses)
{
if(Actor->IsA(Class)) return true;
if(CurrentActorClass->ImplementsInterface(Class)) return true;
}
return false;
});
return Ret;
}
FString UGlobalUtilsLibrary::ReferencePathToFilePath(const FString& ReferencePath)
{
FString Ret, Str;
ReferencePath.Split("\'", nullptr, &Str);
Str.Split(".", &Ret, nullptr);
return Ret;
}
FString UGlobalUtilsLibrary::Uint32ToBase64String(uint32 Value)
{
const FString Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@";
FString Result = "";
if (Value == 0) Result = Alphabet.Mid(0, 1);
for (int i = 1; i < 6; i++)
{
uint32 Index = Value % Alphabet.Len();
Result = Alphabet.Mid(Index, 1) + Result;
Value = Value / Alphabet.Len();
}
return Result;
}
TSoftClassPtr<UUserWidget> UGlobalUtilsLibrary::GetSoftWidgetClassFromPath(FString Path)
{
return GetStringToSoftClass<UUserWidget>(Path);
}
bool UGlobalUtilsLibrary::IsEditorPlay()
{
#if WITH_EDITOR
return true;
#else
return false;
#endif
}
void UGlobalUtilsLibrary::EnableComponent(UActorComponent* Component, bool bEnable)
{
NMT_CHECKF(Component);
Component->SetComponentTickEnabled(bEnable);
if (UPrimitiveComponent* PrimitiveComponent = Cast<UPrimitiveComponent>(Component))
{
PrimitiveComponent->SetVisibility(bEnable, true);
PrimitiveComponent->SetHiddenInGame(!bEnable, true);
PrimitiveComponent->SetCollisionEnabled(bEnable ? ECollisionEnabled::QueryAndPhysics : ECollisionEnabled::NoCollision);
}
}
FString UGlobalUtilsLibrary::GetLocalizedStringFromTable(const FName& TableRow)
{
UWorld* World = GEngine->GameViewport->GetWorld();
if (!World) return FString();
UDataDam* DD = GetSharedDataDam(World);
NMT_CHECKF(DD);
const UDataTable* LocalizeDT = DD->GetDataTableByEnum(EDataTableKey::Localization);
FLocalization* LocalizeST = LocalizeDT->FindRow<FLocalization>(TableRow, LocalizeDT->GetName());
if (!LocalizeST) return FString();
UCoreGameUserSettings* UserSetting = UCoreGameUserSettings::GetCoreGameUserSettings();
EGameLanguage CurLanguage = UserSetting->GetGamePlayOption().Setting_Language;
FString OutputString = FString();
switch (CurLanguage)
{
case EGameLanguage::Korea:
{
OutputString = LocalizeST->sKorean;
break;
}
case EGameLanguage::English:
{
OutputString = LocalizeST->sEnglish;
break;
}
default:
{
OutputString = LocalizeST->sEnglish;
break;
}
}
return OutputString;
}
/*NOTE:
베지에 곡선의 드 카스텔조 알고리즘을 사용하여 주어진 제어점 Points에 대한 시간 t에서의 보정위치를 구한다.
Points 배열의 첫번째 인덱스에는 시작점, 마지막 인덱스에는 끝점이 위치해야 한다.
*/
FVector UGlobalUtilsLibrary::GetBezierPointByDeCasteljau(const TArray<FVector>& Points, float t)
{
if(Points.Num() == 1)
return Points[0];
TArray<FVector> NextLevel;
for(int i = 0; i < Points.Num() - 1; ++i)
{
FVector LerpPoint = FMath::Lerp(Points[i], Points[i + 1], t);
NextLevel.Add(LerpPoint);
}
return GetBezierPointByDeCasteljau(NextLevel, t);
}
// FIXME: 프로젝트 이주로 기존에 쓰던 데이터는 삭제됨 새로운 데이터 구조에 맞춰서 수정필요
int32 UGlobalUtilsLibrary::GetEnumIndexFromString(EDataTableKey InEnum, FString InString)
{
int32 Ret = 0;
FString FindEnumType = "E" + EnumToString(InEnum);
UEnum* EnumPtr = FindFirstObjectSafe<UEnum>(*FindEnumType);
if (EnumPtr == nullptr) return Ret;
{
Ret = EnumPtr->GetIndexByNameString(InString);
return Ret;
}
}
FVector UGlobalUtilsLibrary::GetCenterPointBetweenTwoVectors(FVector A, FVector B)
{
return (A + B) * 0.5f;
}
double UGlobalUtilsLibrary::FindAngleBetweenTwoVectors2D(FVector2D A, FVector2D B)
{
A.Normalize();
B.Normalize();
double Scalar = A | B;
double Angle = UKismetMathLibrary::DegAcos(Scalar);
Angle = (A ^ B) > 0 ? Angle : Angle * -1.0;
return Angle;
}
double UGlobalUtilsLibrary::FindAngleBetweenTwoVectors3D(FVector A, FVector B, EFindAngleAxis EFindAxis)
{
A.Normalize();
B.Normalize();
double Scalar = A | B;
double Angle = UKismetMathLibrary::DegAcos(Scalar);
FVector CrossVector = A ^ B;
switch (EFindAxis)
{
case EFindAngleAxis::EForward:
Angle = CrossVector.X > 0 ? Angle : Angle * -1.0;
break;
case EFindAngleAxis::EUp:
Angle = CrossVector.Z > 0 ? Angle : Angle * -1.0;
break;
case EFindAngleAxis::ERight:
Angle = CrossVector.Y > 0 ? Angle : Angle * -1.0;
break;
}
return Angle;
}
bool UGlobalUtilsLibrary::SuggestProjectileVelocityAtLocation(const UObject* WorldContextObject,
FVector& OutLaunchVelocity, const FVector& ProjectileStartLocation, const FVector& TargetLocation, const float DesiredArcHeight, double GravityZOverride,
double TimeToTarget)
{
if (!GEngine) return false;
if (TargetLocation == FVector::ZeroVector) return false;
const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
if (!World) return false;
const double Gravity = FMath::IsNearlyZero(GravityZOverride) ? World->GetGravityZ() : GravityZOverride;
const double StartZ = ProjectileStartLocation.Z;
const double TargetZ = TargetLocation.Z;
const double ApexZ = TargetZ + DesiredArcHeight;
if (ApexZ <= StartZ || ApexZ <= TargetZ) return false;
const double Sqrt = FMath::Sqrt(2.0 * FMath::Abs(Gravity) * (ApexZ - StartZ));
const double Up = Sqrt / FMath::Abs(Gravity);
const double Down = FMath::Sqrt(2.0 * (ApexZ - TargetZ) / FMath::Abs(Gravity));
const double Time = Up + Down;
const FVector Delta = TargetLocation - ProjectileStartLocation;
const FVector DeltaXY = FVector(Delta.X, Delta.Y, 0.0);
const FVector VelXY = DeltaXY / Time;
OutLaunchVelocity = FVector(VelXY.X, VelXY.Y, Sqrt);
return true;
}
// EX: (X=0.0000,Y=0.0000,Z=0.0000) -> FVector3D
FVector UGlobalUtilsLibrary::StringToVector3D(FString& InString)
{
FString S = InString.Mid(1, InString.Len() - 2);
TArray<FString> ParseString;
S.ParseIntoArray(ParseString, TEXT(","));
NMT_MSG_CHECKF(ParseString.Num() == 3, "String Vector Has Fewer Than Three Elements");
float X = FCString::Atod(*ParseString[0] + 2);
float Y = FCString::Atod(*ParseString[1] + 2);
float Z = FCString::Atod(*ParseString[2] + 2);
FVector Ret = FVector(X, Y, Z);
return Ret;
}
FString UGlobalUtilsLibrary::DivideString(const int Count, FString& InString)
{
if (InString.Len() < Count) return FString();
FString Ret = InString.Left(Count);
InString.RemoveAt(0, Count);
return Ret;
}
void UGlobalUtilsLibrary::DebugBreak(const FString& MessageString)
{
checkf(0, TEXT("%s"), *MessageString);
}