in Ambit/Source/Ambit/Actors/Spawners/SpawnWithHoudini.spec.cpp [37:524]
void SpawnWithHoudiniSpec::Define()
{
BeforeEach([this]()
{
World = FAutomationEditorCommonUtils::CreateNewMap();
Spawner = World->SpawnActor<ASpawnWithHoudini>();
const FString Path = "StaticMesh'/Engine/BasicShapes/Plane.Plane'";
FActorSpawnParameters Params;
SurfaceActorName = "Plane";
Params.Name = FName(*SurfaceActorName);
UStaticMesh* StaticMesh = LoadObject<UStaticMesh>(nullptr, *Path, nullptr, LOAD_None, nullptr);
const FVector Location(0, 0, 0);
const FRotator Rotation(0, 0, 0);
const FTransform Transform(Rotation, Location);
SurfaceActor = World->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), Transform, Params);
SurfaceActor->SetActorLabel(SurfaceActorName);
SurfaceActor->SetMobility(EComponentMobility::Movable);
SurfaceActor->GetStaticMeshComponent()->SetStaticMesh(StaticMesh);
Tag = "SurfaceTag";
SurfaceActor->Tags.Add(FName(Tag));
const FVector Scale3D(5, 5, 5);
SurfaceActor->SetActorScale3D(Scale3D);
});
Describe("GenerateObstacles() and PopulateParameters()", [this]()
{
Describe("When no HDA Selected", [this]()
{
It("Should return no spawned actors with no configuration to get SpawnedActor location", [this]()
{
Spawner->GenerateObstacles();
TestEqual("The array of UHoudiniPublicAPIAssetWrapper is empty since there are no Actor spawned.",
Spawner->GetSpawnedActors().Num(), 0);
});
It(
"Should return no spawned actors with configuration that has surface actor name when MatchBy is NameOrTags",
[this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->GenerateObstacles();
TestEqual("The array of UHoudiniPublicAPIAssetWrapper is empty since there are no Actor spawned.",
Spawner->GetSpawnedActors().Num(), 0);
});
It(
"Should return no spawned actors with configuration that has surface actor name and tag when MatchBy is NameAndTags",
[this]()
{
Spawner->MatchBy = NameAndTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->GenerateObstacles();
TestEqual("The array of UHoudiniPublicAPIAssetWrapper is empty since there are no Actor spawned.",
Spawner->GetSpawnedActors().Num(), 0);
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
Describe("When one HDA is selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
});
It("Should return SpawnedActors when configuration has surface actor name when MatchBy is NameOrTags",
[this]()
{
Spawner->GenerateObstacles();
TestEqual("The array of UHoudiniPublicAPIAssetWrapper is not empty.",
Spawner->HoudiniAssetDetails[0].SpawnedActors.Num(), 2);
});
It(
"Should not return SpawnedActors when no configuration doesn't have surface actor name when MatchBy is NameOrTags",
[this]()
{
Spawner->SurfaceNamePattern = "";
Spawner->SurfaceTags.Empty();
Spawner->GenerateObstacles();
TestEqual("The array of UHoudiniPublicAPIAssetWrapper is empty.",
Spawner->HoudiniAssetDetails[0].SpawnedActors.Num(), 0);
});
Describe("PopulateParameters() (When loading with Houdini)", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PreInstantiationDone = Done;
Spawner->GenerateObstacles();
});
It("Should generate ParamsToRandomProperly for valid HoudiniAssetDetails", [this]()
{
TestEqual("HoudiniAssetDetails ParamsToRandom contains only one item",
Spawner->HoudiniAssetDetails[0].ParamsToRandom.Num(), 1);
TestTrue("HoudiniAssetDetails ParamsToRandom's item is 'random_seed'",
Spawner->HoudiniAssetDetails[0].ParamsToRandom.Contains("random_seed"));
});
});
});
Describe("When multiple HDA are selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 3; // 3 is chosen as the first seed that spawns both HDA
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
FHoudiniLoadableAsset NewAsset;
NewAsset.HDAToLoad = SampleCubeHDA;
Spawner->HoudiniAssetDetails.Add(NewAsset);
});
It("Will have the correct output for item's SpawnedActors when multiple HoudiniAssetDetails are valid",
[this]()
{
Spawner->GenerateObstacles();
TestTrue("First HoudiniAssetDetails contains items.",
Spawner->HoudiniAssetDetails[0].SpawnedActors.Num() > 0);
TestTrue("First HoudiniAssetDetails contains items.",
Spawner->HoudiniAssetDetails[1].SpawnedActors.Num() > 0);
});
Describe("PopulateParameters() (When loading with Houdini)", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PreInstantiationDone = Done;
Spawner->GenerateObstacles();
});
It("Will generate ParamsToRandomProperly for valid HoudiniAssetDetails", [this]()
{
TestEqual("HoudiniAssetDetails ParamsToRandom contains only one item",
Spawner->HoudiniAssetDetails[1].ParamsToRandom.Num(), 1);
TestTrue("HoudiniAssetDetails ParamsToRandom's item is 'random_seed'",
Spawner->HoudiniAssetDetails[1].ParamsToRandom.Contains("random_seed"));
});
});
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
Describe("GetSpawnedActors()", [this]()
{
Describe("When one HDA is selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
});
It("Will have correct number of actors in list", [this]()
{
Spawner->GenerateObstacles();
const int32 InnerSpawnedActorCount = Spawner->HoudiniAssetDetails[0].SpawnedActors.Num();
TestEqual("GetSpawnedActor reflects AssetDetails SpawnedActors", Spawner->GetSpawnedActors().Num(),
InnerSpawnedActorCount);
TestEqual("GetSpawnedActor has the correct number of actors", Spawner->GetSpawnedActors().Num(), 2);
});
});
Describe("When multiple HDA are selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 3; // 3 is chosen as the first seed that spawns both HDA
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
FHoudiniLoadableAsset NewAsset;
NewAsset.HDAToLoad = SampleCubeHDA;
Spawner->HoudiniAssetDetails.Add(NewAsset);
});
It("Will have the correct output for item's SpawnedActors when multiple HoudiniAssetDetails are valid",
[this]()
{
Spawner->GenerateObstacles();
const int32 InnerSpawnedActorCount = Spawner->HoudiniAssetDetails[0].SpawnedActors.Num() + Spawner->
HoudiniAssetDetails[1].SpawnedActors.Num();
TestEqual("GetSpawnedActor reflects AssetDetails SpawnedActors", Spawner->GetSpawnedActors().Num(),
InnerSpawnedActorCount);
TestEqual("GetSpawnedActor has the correct number of actors", Spawner->GetSpawnedActors().Num(), 2);
});
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
Describe("RandomizeActor()", [this]()
{
Describe("When a single HDA is selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 1;
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
});
Describe("When randomizing without modifying parameters", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PostProcessingDone = Done;
Spawner->GenerateObstacles();
});
It("Will generate the same parameter every time", [this]()
{
const float ExpectedNumber = 78.2120209f;
float OutSeedNumber;
const TWeakObjectPtr<UHoudiniPublicAPIAssetWrapper> FirstAsset = Spawner->HoudiniAssetDetails[0].
SpawnedActors[0];
const bool bLoaded = FirstAsset->GetFloatParameterValue("random_seed", OutSeedNumber);
TestTrue("Asset parameter was loaded properly", bLoaded);
TestEqual("Seed value is expected number", OutSeedNumber, ExpectedNumber);
});
});
Describe("When randomizing with removing parameters", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PostProcessingDone = Done;
// Set to fake, as to not allow params to re-generate.
Spawner->HoudiniAssetDetails[0].ParamsToRandom.Add("fake");
Spawner->GenerateObstacles();
});
It("Will generate the base parameter regardless", [this]()
{
const float ExpectedNumber = 0.550000012;
float OutSeedNumber;
const TWeakObjectPtr<UHoudiniPublicAPIAssetWrapper> FirstAsset = Spawner->HoudiniAssetDetails[0].
SpawnedActors[0];
const bool bLoaded = FirstAsset->GetFloatParameterValue("random_seed", OutSeedNumber);
TestTrue("Asset parameter was loaded properly", bLoaded);
TestEqual("Seed value is expected number", OutSeedNumber, ExpectedNumber);
});
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
Describe("When multiple HDA are selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 3; // 3 is chosen as the first seed that spawns both HDA
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
FHoudiniLoadableAsset NewAsset;
NewAsset.HDAToLoad = SampleCubeHDA;
Spawner->HoudiniAssetDetails.Add(NewAsset);
});
Describe("When randomizing without modifying parameters", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PostProcessingDone = Done;
Spawner->GenerateObstacles();
});
It("Will generate the same parameter every time", [this]()
{
const float ExpectedNumber = 38.0790367f;
float OutSeedNumber;
const TWeakObjectPtr<UHoudiniPublicAPIAssetWrapper> FirstAsset = Spawner->HoudiniAssetDetails[1].
SpawnedActors[0];
const bool bLoaded = FirstAsset->GetFloatParameterValue("random_seed", OutSeedNumber);
TestTrue("Asset parameter was loaded properly", bLoaded);
TestEqual("Seed value is expected number", OutSeedNumber, ExpectedNumber);
});
});
Describe("When randomizing with removing parameters", [this]()
{
LatentBeforeEach([this](FDoneDelegate const& Done)
{
Spawner->PostProcessingDone = Done;
// Set to fake, as to not allow params to re-generate.
Spawner->HoudiniAssetDetails[1].ParamsToRandom.Add("fake");
Spawner->GenerateObstacles();
});
It("Will generate the base parameter when modified", [this]()
{
const float ExpectedNumber = 0.550000012f;
// We do not modify the first set of objects, so their numbers should not be the ExpectedNumber.
const bool AnyExpected = Spawner->HoudiniAssetDetails[0].SpawnedActors.ContainsByPredicate(
[ExpectedNumber](TWeakObjectPtr<UHoudiniPublicAPIAssetWrapper> Asset)
{
float OutSeedNumber;
Asset->GetFloatParameterValue("random_seed", OutSeedNumber);
return OutSeedNumber == ExpectedNumber;
});
// We remove the randomization from this set, so all of their numbers should be the default value.
const bool AnyNotExpected = Spawner->HoudiniAssetDetails[1].SpawnedActors.ContainsByPredicate(
[ExpectedNumber](TWeakObjectPtr<UHoudiniPublicAPIAssetWrapper> Asset)
{
float OutSeedNumber;
Asset->GetFloatParameterValue("random_seed", OutSeedNumber);
return OutSeedNumber != ExpectedNumber;
});
TestFalse("Unmodified list should have randomized parameters", AnyExpected);
TestFalse("Modified list should not have randomized parameters", AnyNotExpected);
});
});
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
Describe("ClearObstacles()", [this]()
{
Describe("When a single HDA is selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 1;
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
Spawner->GenerateObstacles();
});
It("Should reset when all actors were available", [this]()
{
Spawner->ClearObstacles();
TestEqual("Spawned Actors should reset to 0", Spawner->HoudiniAssetDetails[0].SpawnedActors.Num(), 0);
});
It("Should reset when all actors even when not available (Destroyed by Houdini Deletion)", [this]()
{
Spawner->HoudiniAssetDetails[0].SpawnedActors[1]->DeleteInstantiatedAsset();
Spawner->HoudiniAssetDetails[0].SpawnedActors[0]->DeleteInstantiatedAsset();
Spawner->ClearObstacles();
TestEqual("Spawned Actors should reset to 0", Spawner->HoudiniAssetDetails[0].SpawnedActors.Num(), 0);
});
It("Should reset when all actors even when not available (Destroyed by UE Deletion)", [this]()
{
const EMatchBy MatchBy = EMatchBy::NameOrTags;
const FString SurfaceNamePattern = "sample_cube";
const TArray<FName> SurfaceTags;
const TArray<AActor*> SurfaceActors = AmbitWorldHelpers::GetActorsByMatchBy(
MatchBy, SurfaceNamePattern, SurfaceTags);
for (auto* Actor : SurfaceActors)
{
Actor->Destroy();
}
Spawner->ClearObstacles();
TestEqual("Spawned Actors should reset to 0", Spawner->HoudiniAssetDetails[0].SpawnedActors.Num(), 0);
});
});
Describe("When multiple HDA are selected", [this]()
{
BeforeEach([this]()
{
Spawner->MatchBy = NameOrTags;
Spawner->SurfaceNamePattern = SurfaceActorName;
Spawner->SurfaceTags.Add(FName(Tag));
Spawner->RandomSeed = 3; // 3 is chosen as the first seed that spawns both HDA
UHoudiniAsset* SampleCubeHDA = Cast<UHoudiniAsset>(StaticLoadObject(
UHoudiniAsset::StaticClass(), nullptr,
TEXT("HoudiniAsset'/Ambit/Test/Props/sample_cube.sample_cube'")));
Spawner->HoudiniAssetDetails[0].HDAToLoad = SampleCubeHDA;
FHoudiniLoadableAsset NewAsset;
NewAsset.HDAToLoad = SampleCubeHDA;
Spawner->HoudiniAssetDetails.Add(NewAsset);
});
});
AfterEach([this]()
{
Spawner->ResetObstacleSpawner();
});
});
AfterEach([this]()
{
SurfaceActor->Destroy();
SurfaceActor = nullptr;
});
}