in Ambit/Source/Ambit/Utils/AmbitWorldHelpers.spec.cpp [41:1292]
void AmbitWorldHelpersSpec::Define()
{
BeforeEach([this]()
{
// Create a empty test map;
World = FAutomationEditorCommonUtils::CreateNewMap();
TestNotNull("Check if World is properly created", World);
const FString Path = "StaticMesh'/Engine/BasicShapes/Plane.Plane'";
FActorSpawnParameters Params;
ExpectedActorName = "Plane";
Params.Name = FName(*ExpectedActorName);
UStaticMesh* StaticMesh = LoadObject<UStaticMesh>(nullptr, *Path, nullptr, LOAD_None, nullptr);
if (StaticMesh == nullptr || !StaticMesh->IsValidLowLevelFast())
{
UE_LOG(LogAmbit, Error, TEXT("StaticMesh is not there"));
}
FVector Location(0, 0, 0);
FRotator Rotation(0, 0, 0);
FTransform Transform(Rotation, Location);
TestSurfaceActor = World->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), Transform, Params);
if (TestSurfaceActor == nullptr)
{
UE_LOG(LogAmbit, Error, TEXT("TestSurfaceActor is null pointer."));
}
TestSurfaceActor->SetActorLabel(ExpectedActorName);
TestSurfaceActor->SetMobility(EComponentMobility::Movable);
TestSurfaceActor->GetStaticMeshComponent()->SetStaticMesh(StaticMesh);
ExpectedTag_1 = "Tag_1";
TestSurfaceActor->Tags.Add(FName(ExpectedTag_1));
FActorSpawnParameters NewParams;
FString NewParamName = "Component";
NewParams.Name = FName(*NewParamName);
FVector NewLocation(0, 0, 100);
FRotator NewRotation(0, 0, 0);
FTransform NewTransform(NewRotation, NewLocation);
TestComponentActor = World->SpawnActor<AActor>(AActor::StaticClass(), NewTransform, NewParams);
RealBox = NewObject<UBoxComponent>(TestComponentActor, UBoxComponent::StaticClass(), "RealBox");
RealSpline = NewObject<USplineComponent>(TestComponentActor, USplineComponent::StaticClass(), "RealSpline");
});
Describe("GetActorsByMatchBy()", [this]()
{
Describe("MatchBy::NameOrTags", [this]()
{
Describe("Single tag", [this]()
{
It("with correct name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with wrong name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with wrong name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with empty name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with empty name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with correct name and empty tag list", [this]()
{
const TArray<FName> TagList;
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with wrong name and empty tag list", [this]()
{
const TArray<FName> TagList;
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with empty name and empty tag list", [this]()
{
const TArray<FName> TagList;
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
});
Describe("Multiple tags", [this]()
{
BeforeEach([this]()
{
ExpectedTag_2 = "Tag_2";
TestSurfaceActor->Tags.Add(FName(ExpectedTag_2));
});
It("with correct name and correct tags, expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName(ExpectedTag_2));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and correct tags but in different order, expected to get a matched actor",
[this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_2));
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and only one contained tag, expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and a not contained tag, expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName("WrongTag"));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with wrong name and a not contained tag, expected no matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName("WrongTag"));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameOrTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
});
});
Describe("MatchBy::NameAndTags", [this]()
{
Describe("Single Tag", [this]()
{
It("with correct name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with wrong name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with wrong name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with empty name and correct tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with empty name and wrong tag", [this]()
{
TArray<FName> TagList;
TagList.Add(FName("WrongTag"));
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with correct name and empty tag", [this]()
{
const TArray<FName> TagList;
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with wrong name and empty tag", [this]()
{
const TArray<FName> TagList;
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with empty name and empty tag", [this]()
{
const TArray<FName> TagList;
const FString EmptyName = "";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, EmptyName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
});
Describe("Multiple tags", [this]()
{
BeforeEach([this]()
{
ExpectedTag_2 = "Tag_2";
TestSurfaceActor->Tags.Add(FName(ExpectedTag_2));
});
It("with correct name and correct tags, expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName(ExpectedTag_2));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and correct tags but in different order, expected to get a matched actor",
[this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_2));
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and only one contained tag, expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("with correct name and a not contained tag, expected no matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName("WrongTag"));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
It("with wrong name and correct tags, expected no matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
TagList.Add(FName(ExpectedTag_2));
const FString WrongName = "Cube";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, WrongName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
});
});
Describe("Special Characters in the name", [this]()
{
BeforeEach([this]()
{
ExpectedActorName = "~!@#$%^&*()_+`-={}|[]\'<>?,./";
TestSurfaceActor->SetActorLabel(ExpectedActorName);
});
It("when the name only contains *_+-<>?, the name can be checked and we expect to get a matched actor",
[this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString NamePatternWithSpecialCharacter = "*_+-<>?";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, NamePatternWithSpecialCharacter, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
It("when the name contains special characters except *_+-<>?, it will not find the matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTag_1));
const FString NamePatternWithSpecialCharacter = "~!@#$%^&()";
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, NamePatternWithSpecialCharacter, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 0);
});
});
Describe("Special Characters in the tag", [this]()
{
BeforeEach([this]()
{
ExpectedTagWithSpecialCharacters = "~!@#$%^&*()_+`-={}|[]\'<>?,./";
TestSurfaceActor->Tags.Add(FName(ExpectedTagWithSpecialCharacters));
});
It("expected to get a matched actor", [this]()
{
TArray<FName> TagList;
TagList.Add(FName(ExpectedTagWithSpecialCharacters));
const TArray<AActor*> ResultActors = AmbitWorldHelpers::GetActorsByMatchBy(
EMatchBy::NameAndTags, ExpectedActorName, TagList);
TestEqual("The number of matched actor", ResultActors.Num(), 1);
});
});
});
Describe("LineTraceBelowWorldPoint()", [this]()
{
It("when the LineStart is above the actor, the line trace will hit the actor", [this]()
{
const FVector LineStart(0, 0, 10);
const FHitResult& Hit = AmbitWorldHelpers::LineTraceBelowWorldPoint(LineStart);
TestTrue("The line trace hit the actor", Hit.IsValidBlockingHit());
});
It("when the LineStart is below the actor, the line trace will not hit the actor", [this]()
{
const FVector LineStart(0, 0, -10);
const FHitResult& Hit = AmbitWorldHelpers::LineTraceBelowWorldPoint(LineStart);
TestFalse("The line trace doesn't hit the actor", Hit.IsValidBlockingHit());
});
});
Describe("GenerateRandomLocationsFromBox()", [this]()
{
It("will return an empty array if Box is invalid", [this]()
{
AddExpectedError(TEXT("Invalid box component."), EAutomationExpectedErrorFlags::Exact, 1);
UBoxComponent* EmptyBox = nullptr;
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
EmptyBox, ActorsToSearch, RandomSeed, true);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestEqual("The number of Transforms is 0.", Transforms.Num(), 0);
});
It("Can generate random locations when Box's extent is large enough", [this]()
{
RealBox->SetBoxExtent(FVector(300, 300, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestTrue("The number of Transforms is greater than 0.", Transforms.Num() > 0);
});
It("Cannot generate random locations when Box's extent is not large enough", [this]()
{
RealBox->SetBoxExtent(FVector(0, 0, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestEqual("The number of Transforms is equal to 0.", Transforms.Num(), 0);
});
It("Can snap to surface below if provided in ActorsToSearch array", [this]()
{
RealBox->SetBoxExtent(FVector(200, 200, 0));
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, false, DensityMin, DensityMax);
for (const FTransform& OneTransform : Transforms)
{
TestEqual("All of the generated locations have snapped to the surface provided.",
TestSurfaceActor->GetActorLocation().Z, OneTransform.GetLocation().Z, 0.05f);
}
});
It("Can snap to unspecified surface below if bSnapToSurfaceBelow is true when ActorsToSearch is empty", [this]()
{
RealBox->SetBoxExtent(FVector(200, 200, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = true;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
bool bAllLocationsSnapped = true;
for (const FTransform& OneTransform : Transforms)
{
TestEqual("All of the generated locations have snapped to the surface below.",
TestSurfaceActor->GetActorLocation().Z, OneTransform.GetLocation().Z, 0.05f);
}
});
It("Will generate random rotations only within the provided range", [this]()
{
const float RotationMin = 30.0f;
const float RotationMax = 90.0f;
RealBox->SetBoxExtent(FVector(300, 300, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, false, DensityMin, DensityMax, RotationMin, RotationMax);
for (const FTransform& OneTransform : Transforms)
{
UE_LOG(LogAmbit, Display, TEXT("Yaw: %f"), OneTransform.Rotator().Yaw);
TestTrue("We expect all of the generated rotations to be within the provided range",
RotationMin < OneTransform.Rotator().Yaw && RotationMax > OneTransform.Rotator().Yaw);
}
});
It("Use same random seed will have the exact same FTransform set", [this]()
{
RealBox->SetBoxExtent(FVector(200, 200, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
TArray<FTransform> ExpectedArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of ExpectedArray is: %d"), ExpectedArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("With the same random seed, we expect they will have the same size.", ActualArray.Num(),
ExpectedArray.Num());
for (int i = 0; i < ActualArray.Num(); ++i)
{
TestTrue("With the same random seed, we expect each corresponding elements are same.",
ExpectedArray[i].Equals(ActualArray[i]));
}
});
It("Use different random seed will have different set", [this]()
{
RealBox->SetBoxExtent(FVector(200, 200, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed_1 = 0;
const int32 RandomSeed_2 = 1;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
TArray<FTransform> ExpectedArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed_1, bSnapToSurfaceBelow, DensityMin, DensityMax);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed_2, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of ExpectedArray is: %d"), ExpectedArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
bool bNotEqual = false;
if (ExpectedArray.Num() != ActualArray.Num())
{
bNotEqual = true;
}
else
{
for (int i = 0; i < ActualArray.Num(); ++i)
{
// At least one element is unique to the second array
if (!ExpectedArray[i].Equals(ActualArray[i]))
{
bNotEqual = true;
break;
}
}
}
TestTrue("With different random seeds, we expect it will have different sets.", bNotEqual);
});
It("Will generate the right amount of FTransforms for a rotated box", [this]()
{
RealBox->SetBoxExtent(FVector(500, 500, 0));
RealBox->SetRelativeRotation(FRotator(0, 45, 0).Quaternion());
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform> RotatedArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
RealBox->SetRelativeRotation(FRotator(0, 0, 0).Quaternion());
const TArray<FTransform> NormalArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of RotatedArray is: %d"), RotatedArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of NormalArray is: %d"), NormalArray.Num());
TestEqual("The rotated box and the normal box should generate the same number of FTransforms.",
NormalArray.Num(), RotatedArray.Num());
});
It("Can handle when DensityMin is greater than DensityMax", [this]()
{
AddExpectedError(
TEXT("DensityMin is greater than DensityMax. No actors spawned."), EAutomationExpectedErrorFlags::Exact,
1);
RealBox->SetBoxExtent(FVector(500, 500, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMax, DensityMin);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
It("Can handle when RotationMin is greater than RotationMax", [this]()
{
AddExpectedError(
TEXT("RotationMin is greater than RotationMax. No actors spawned."),
EAutomationExpectedErrorFlags::Exact, 1);
RealBox->SetBoxExtent(FVector(500, 500, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax, 90.f, 45.f);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
It("will generate zero locations if bSnapToSurfaceBelow is true but there are no surfaces below", [this]()
{
TestComponentActor->SetActorLocation(FVector(0, 0, -100));
RealBox->SetBoxExtent(FVector(500, 500, 0));
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = true;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TestComponentActor->SetActorLocation(FVector(0, 0, 0));
TestEqual("The array is empty", Transforms.Num(), 0);
});
It("will generate zero locations if a hit surface is specified but the bounding box is below it", [this]()
{
TestComponentActor->SetActorLocation(FVector(0, 0, -100));
RealBox->SetBoxExtent(FVector(500, 500, 0));
const FVector Scale3D(100, 100, 0);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Push(TestSurfaceActor);
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromBox(
RealBox, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TestComponentActor->SetActorLocation(FVector(0, 0, 0));
TestEqual("The array is empty", Transforms.Num(), 0);
});
});
Describe("GenerateRandomLocationsFromSpline()", [this]()
{
It("will return an empty array if Spline is invalid", [this]()
{
AddExpectedError(TEXT("Invalid spline component."), EAutomationExpectedErrorFlags::Exact, 1);
USplineComponent* EmptySpline = nullptr;
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
EmptySpline, ActorsToSearch, RandomSeed, true);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestEqual("The number of Transforms is equal to 0.", Transforms.Num(), 0);
});
It("can generate random locations on a closed loop Spline", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
RealSpline->SetClosedLoop(true);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false);
RealSpline->SetClosedLoop(false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestTrue("The number of Transforms is greater than 0.", Transforms.Num() > 0);
});
It("Can generate random locations when Spline's length is large enough", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestTrue("The number of Transforms is greater than 0.", Transforms.Num() > 0);
});
It("Cannot generate random locations when Spline's length is not large enough", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 1, 100), ESplineCoordinateSpace::World);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestEqual("The number of Transforms is equal to 0.", Transforms.Num(), 0);
});
It("Can snap to surface below if provided in ActorsToSearch array", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.02f;
const float DensityMax = 0.5f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
for (const FTransform& OneTransform : Transforms)
{
UE_LOG(LogAmbit, Display, TEXT("Test Surface: %f, Object: %f"), TestSurfaceActor->GetActorLocation().Z,
OneTransform.GetLocation().Z);
TestEqual("The generated location has snapped to the surface provided.",
TestSurfaceActor->GetActorLocation().Z, OneTransform.GetLocation().Z, 0.05f);
}
});
It("Can snap to unspecified surface below if bSnapToSurfaceBelow is true when ActorsToSearch is empty", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = true;
const float DensityMin = 0.02f;
const float DensityMax = 0.5f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
for (const FTransform& OneTransform : Transforms)
{
UE_LOG(LogAmbit, Display, TEXT("Test Surface: %f, Object: %f"), TestSurfaceActor->GetActorLocation().Z,
OneTransform.GetLocation().Z);
TestEqual("The generated location has snapped to the surface below.",
TestSurfaceActor->GetActorLocation().Z, OneTransform.GetLocation().Z, 0.05f);
}
});
It("Will generate random rotations only within the provided range", [this]()
{
const float RotationMin = 30.0f;
const float RotationMax = 90.0f;
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const float DensityMin = 0.02f;
const float DensityMax = 0.5f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false, DensityMin, DensityMax, RotationMin, RotationMax);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
for (const FTransform& OneTransform : Transforms)
{
UE_LOG(LogAmbit, Display, TEXT("Yaw: %f"), OneTransform.Rotator().Yaw);
TestTrue("We expect all of the generated rotations to be within the provided range",
RotationMin < OneTransform.Rotator().Yaw && RotationMax > OneTransform.Rotator().Yaw);
}
});
It("Use same random seed will have the exact same FTransform set", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.02f;
const float DensityMax = 0.5f;
TArray<FTransform> ExpectedArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of ExpectedArray is: %d"), ExpectedArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("With the same random seed, we expect they will have the same size.", ActualArray.Num(),
ExpectedArray.Num());
for (int i = 0; i < ActualArray.Num(); ++i)
{
TestTrue("With the same random seed, we expect each corresponding elements are same.",
ExpectedArray[i].Equals(ActualArray[i]));
}
});
It("Use different random seed will have different set", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed_1 = 0;
const int32 RandomSeed_2 = 1;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.02f;
const float DensityMax = 0.5f;
TArray<FTransform> DifferentArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed_1, bSnapToSurfaceBelow, DensityMin, DensityMax);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed_2, bSnapToSurfaceBelow, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of DifferentArray is: %d"), DifferentArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
bool bNotEqual = false;
if (DifferentArray.Num() != ActualArray.Num())
{
bNotEqual = true;
}
else
{
for (int i = 0; i < ActualArray.Num(); ++i)
{
// At least one element is unique to the second array
if (!DifferentArray[i].Equals(ActualArray[i]))
{
bNotEqual = true;
break;
}
}
}
TestTrue("With different random seeds, we expect it will have different sets.", bNotEqual);
});
It("Can handle when DensityMin is greater than DensityMax", [this]()
{
AddExpectedError(
TEXT("DensityMin is greater than DensityMax. No actors spawned."), EAutomationExpectedErrorFlags::Exact,
1);
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMax, DensityMin);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
It("Can handle when RotationMin is greater than RotationMax", [this]()
{
AddExpectedError(
TEXT("RotationMin is greater than RotationMax. No actors spawned."),
EAutomationExpectedErrorFlags::Exact, 1);
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax, 90.f, 45.f);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
It("will generate zero locations if bSnapToSurfaceBelow is true but there are no surfaces below", [this]()
{
TestComponentActor->SetActorLocation(FVector(0, 0, -100));
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = true;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TestComponentActor->SetActorLocation(FVector(0, 0, 0));
TestEqual("The array is empty", Transforms.Num(), 0);
});
It("will generate zero locations if a hit surface is specified but the spline is below it", [this]()
{
TestComponentActor->SetActorLocation(FVector(0, 0, -100));
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const FVector Scale3D(100, 100, 0);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Push(TestSurfaceActor);
const int32 RandomSeed = 0;
const bool bSnapToSurfaceBelow = false;
const float DensityMin = 0.5f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, bSnapToSurfaceBelow, DensityMin, DensityMax);
TestComponentActor->SetActorLocation(FVector(0, 0, 0));
TestEqual("The array is empty", Transforms.Num(), 0);
});
It("Will generate objects relative to spline rotation if bFollowSplineRotation is true", [this]()
{
const bool bFollowSplineRotation = true;
const float RotationMin = 120.0f;
const float RotationMax = 120.0f;
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 1000, 0), ESplineCoordinateSpace::World);
const TArray<AActor*> ActorsToSearch;
const int32 RandomSeed = 0;
const float DensityMin = 1.0f;
const float DensityMax = 1.0f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromSpline(
RealSpline, ActorsToSearch, RandomSeed, false, DensityMin, DensityMax, RotationMin, RotationMax,
bFollowSplineRotation);
const float ExpectedRotation = 210.0f;
for (const FTransform& OneTransform : Transforms)
{
const float SplineRotation = OneTransform.Rotator().GetDenormalized().Yaw;
TestTrue(
"We expect the determined transform to be equal to the sum of the spline rotation and min rotation value",
FMath::IsNearlyEqual(SplineRotation, ExpectedRotation, 0.01f));
}
});
});
Describe("GenerateRandomLocationsFromActor()", [this]()
{
It("Can generate random locations when SurfaceActor is large enough", [this]()
{
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestTrue("The number of Transforms is greater than 1.", Transforms.Num() > 0);
});
It("Cannot generate random locations when SurfaceActor is not large enough", [this]()
{
const FVector Scale3D(1, 1, 1);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of Transforms is: %d"), Transforms.Num());
TestEqual("The number of Transforms is equal to 0.", Transforms.Num(), 0);
});
It("Will generate random rotations only within the provided range", [this]()
{
const float RotationMin = 30.0f;
const float RotationMax = 90.0f;
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform>& Transforms = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax, RotationMin, RotationMax);
for (const FTransform& OneTransform : Transforms)
{
UE_LOG(LogAmbit, Display, TEXT("Yaw: %f"), OneTransform.Rotator().Yaw);
TestTrue("We expect all of the generated rotations to be within the provided range",
RotationMin < OneTransform.Rotator().Yaw && RotationMax > OneTransform.Rotator().Yaw);
}
});
It("Use same random seed will have the exact same FTransform set", [this]()
{
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
TArray<FTransform> ExpectedArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax);
//TSet<FTransform> ExpectedSet = TSet<FTransform>(ExpectedArray);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax);
//TSet<FTransform> ActualSet = TSet<FTransform>(ActualArray);
UE_LOG(LogAmbit, Display, TEXT("The number of ExpectedArray is: %d"), ExpectedArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("With the same random seed, we expect they will have the same size.", ActualArray.Num(),
ExpectedArray.Num());
for (int i = 0; i < ActualArray.Num(); ++i)
{
TestTrue("With the same random seed, we expect each corresponding elements are same.",
ExpectedArray[i].Equals(ActualArray[i]));
}
});
It("Use different random seed will have different set", [this]()
{
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed_1 = 0;
const int32 RandomSeed_2 = 1;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
TArray<FTransform> DifferentArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed_1, DensityMin, DensityMax);
TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed_2, DensityMin, DensityMax);
UE_LOG(LogAmbit, Display, TEXT("The number of DifferentArray is: %d"), DifferentArray.Num());
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
bool bNotEqual = false;
if (DifferentArray.Num() != ActualArray.Num())
{
bNotEqual = true;
}
else
{
for (int i = 0; i < ActualArray.Num(); ++i)
{
// At least one element is unique to the second array
if (!DifferentArray[i].Equals(ActualArray[i]))
{
bNotEqual = true;
break;
}
}
}
TestTrue("With different random seeds, we expect it will have different sets.", bNotEqual);
});
It("Can handle when DensityMin is greater than DensityMax", [this]()
{
AddExpectedError(
TEXT("DensityMin is greater than DensityMax. No actors spawned."), EAutomationExpectedErrorFlags::Exact,
1);
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMax, DensityMin);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
It("Can handle when RotationMin is greater than RotationMax", [this]()
{
AddExpectedError(
TEXT("RotationMin is greater than RotationMax. No actors spawned."),
EAutomationExpectedErrorFlags::Exact, 1);
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToSearch;
ActorsToSearch.Add(TestSurfaceActor);
const int32 RandomSeed = 0;
const float DensityMin = 0.05f;
const float DensityMax = 0.2f;
const TArray<FTransform> ActualArray = AmbitWorldHelpers::GenerateRandomLocationsFromActors(
ActorsToSearch, RandomSeed, DensityMin, DensityMax, 90.f, 45.f);
UE_LOG(LogAmbit, Display, TEXT("The number of ActualArray is: %d"), ActualArray.Num());
TestEqual("The array should be empty.", ActualArray.Num(), 0);
});
});
Describe("CheckAndSnapToSurface()", [this]()
{
It("Will return an unchanged FTransform if ActorsToHit is empty and bSnapToSurfaceBelow is false", [this]()
{
const TArray<AActor*> ActorsToHit;
const bool bSnapToSurfaceBelow = false;
const FVector Location(0, 0, 100);
const FRotator Rotation(0, 0, 0);
FTransform Transform(Rotation, Location);
const FTransform OriginalTransform(Rotation, Location);
AmbitWorldHelpers::CheckAndSnapToSurface(Transform, ActorsToHit, bSnapToSurfaceBelow);
TestTrue("We expect the element of the adjusted FTransform to be the same as the original FTransform.",
OriginalTransform.Equals(Transform));
});
It("Will return an changed FTransform if ActorsToHit is NOT empty and bSnapToSurfaceBelow is false", [this]()
{
const FVector Scale3D(100, 100, 100);
TestSurfaceActor->SetActorScale3D(Scale3D);
TArray<AActor*> ActorsToHit;
ActorsToHit.Add(TestSurfaceActor);
const bool bSnapToSurfaceBelow = false;
const FVector Location(0, 0, 100);
const FRotator Rotation(0, 0, 0);
FTransform Transform(Rotation, Location);
const FTransform OriginalTransform(Rotation, Location);
AmbitWorldHelpers::CheckAndSnapToSurface(Transform, ActorsToHit, bSnapToSurfaceBelow);
TestFalse("We expect the element of the adjusted FTransform to be different from the original FTransform.",
OriginalTransform.Equals(Transform));
});
It("Will return an changed FTransform if ActorsToHit is empty and bSnapToSurfaceBelow is true", [this]()
{
const TArray<AActor*> ActorsToHit;
const bool bSnapToSurfaceBelow = true;
const FVector Location(0, 0, 100);
const FRotator Rotation(0, 0, 0);
FTransform Transform(Rotation, Location);
const FTransform OriginalTransform(Rotation, Location);
AmbitWorldHelpers::CheckAndSnapToSurface(Transform, ActorsToHit, bSnapToSurfaceBelow);
TestFalse("We expect the element of the adjusted FTransform to be different from the original FTransform.",
OriginalTransform.Equals(Transform));
});
});
Describe("GenerateFixedLocationsFromSpline()", [this]()
{
It("will return an empty array if Spline is invalid", [this]()
{
AddExpectedError(TEXT("Invalid spline component."), EAutomationExpectedErrorFlags::Exact, 1);
USplineComponent* EmptySpline = nullptr;
const float Distance = 100;
const TArray<FTransform> Transform = AmbitWorldHelpers::GenerateFixedLocationsFromSpline(
EmptySpline, Distance);
UE_LOG(LogAmbit, Display, TEXT("The number of Transform is: %d"), Transform.Num());
TestEqual("The number of Transform is equal to 0.", Transform.Num(), 0);
});
It("can generate fixed locations on a closed loop Spline", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
RealSpline->SetClosedLoop(true);
const float Distance = 100;
const TArray<FTransform> Transform = AmbitWorldHelpers::GenerateFixedLocationsFromSpline(
RealSpline, Distance);
RealSpline->SetClosedLoop(false);
UE_LOG(LogAmbit, Display, TEXT("The number of Transform is: %d"), Transform.Num());
TestTrue("The number of Transform is greater than 0.", Transform.Num() > 0);
});
It("Can generate fixed locations when Spline's length is larger than the distance", [this]()
{
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 5000, 0), ESplineCoordinateSpace::Local);
const float Distance = 100;
const TArray<FTransform> Transform = AmbitWorldHelpers::GenerateFixedLocationsFromSpline(
RealSpline, Distance);
UE_LOG(LogAmbit, Display, TEXT("The number of Transform is: %d"), Transform.Num());
TestTrue("The number of Transform is greater than 0.", Transform.Num() > 0);
});
It("Cannot generate fixed locations when Spline's length is smaller than the distance", [this]()
{
AddExpectedError(
TEXT("Distance must be smaller than the total length of Spline."), EAutomationExpectedErrorFlags::Exact,
1);
RealSpline->SetLocationAtSplinePoint(1, FVector(0, 1, 0), ESplineCoordinateSpace::Local);
const float Distance = 100;
const TArray<FTransform> Transform = AmbitWorldHelpers::GenerateFixedLocationsFromSpline(
RealSpline, Distance);
UE_LOG(LogAmbit, Display, TEXT("The number of Transform is: %d"), Transform.Num());
TestEqual("The Transform array should be empty.", Transform.Num(), 0);
});
});
AfterEach([this]()
{
TestSurfaceActor->Destroy();
TestSurfaceActor = nullptr;
TestComponentActor->Destroy();
TestComponentActor = nullptr;
});
}