Files
UnrealEngineUWP/Engine/Source/Developer/FunctionalTesting/Private/ScreenshotFunctionalTestBase.cpp
Jerome Delattre aa9c726b34 Use GetActorLabel instead of GetName when taking Screenshot with functional test
Actor Name is a property that user can't change directly from the Outliner now. To keep to ScreenshotFunctionalTest actor behavior seamless for the user, we use the actor label instead.
A property is introduced to hold the Actor name on the Client build.

+ update all the necessary screenshot names.

#jira UE-114551
#rb Andrew.Grant, JeanFrancois.Dube, William.Ewen
#rnx

[CL 16152859 by Jerome Delattre in ue5-main branch]
2021-04-28 22:51:13 -04:00

257 lines
8.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ScreenshotFunctionalTestBase.h"
#include "Engine/GameViewportClient.h"
#include "AutomationBlueprintFunctionLibrary.h"
#include "Camera/CameraComponent.h"
#include "Camera/PlayerCameraManager.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/Engine.h"
#if WITH_EDITOR
#include "Editor/EditorEngine.h"
#endif
#include "EngineGlobals.h"
#include "Misc/AutomationTest.h"
#include "Slate/SceneViewport.h"
#include "RenderingThread.h"
#include "Tests/AutomationCommon.h"
#include "Logging/LogMacros.h"
#include "UObject/AutomationObjectVersion.h"
#define WITH_EDITOR_AUTOMATION_TESTS (WITH_EDITOR && WITH_AUTOMATION_TESTS)
DEFINE_LOG_CATEGORY_STATIC(LogScreenshotFunctionalTest, Log, Log)
AScreenshotFunctionalTestBase::AScreenshotFunctionalTestBase(const FObjectInitializer& ObjectInitializer)
: AFunctionalTest(ObjectInitializer)
, ScreenshotOptions(EComparisonTolerance::Low)
, bNeedsViewSettingsRestore(false)
, bNeedsViewportRestore(false)
{
ScreenshotCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
ScreenshotCamera->SetupAttachment(RootComponent);
#if WITH_AUTOMATION_TESTS
ScreenshotEnvSetup = MakeShareable(new FAutomationTestScreenshotEnvSetup());
#endif
}
void AScreenshotFunctionalTestBase::PrepareTest()
{
Super::PrepareTest();
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (PlayerController)
{
PlayerController->SetViewTarget(this, FViewTargetTransitionParams());
}
PrepareForScreenshot();
}
bool AScreenshotFunctionalTestBase::IsReady_Implementation()
{
if ((GetWorld()->GetTimeSeconds() - RunTime) > ScreenshotOptions.Delay)
{
return (GFrameNumber - RunFrame) > 5;
}
return false;
}
void AScreenshotFunctionalTestBase::StartTest()
{
Super::StartTest();
FAutomationTestFramework::Get().OnScreenshotTakenAndCompared.AddUObject(this, &AScreenshotFunctionalTestBase::OnScreenshotTakenAndCompared);
RequestScreenshot();
}
void AScreenshotFunctionalTestBase::OnScreenshotTakenAndCompared()
{
RestoreViewSettings();
FAutomationTestFramework::Get().OnScreenshotTakenAndCompared.RemoveAll(this);
FinishTest(EFunctionalTestResult::Succeeded, TEXT(""));
}
void AScreenshotFunctionalTestBase::PrepareForScreenshot()
{
check(GEngine->GameViewport && GEngine->GameViewport->GetGameViewport());
check(IsInGameThread());
check(!bNeedsViewSettingsRestore && !bNeedsViewportRestore);
#if WITH_AUTOMATION_TESTS
bool bApplyScreenshotSettings = true;
FSceneViewport* GameViewport = GEngine->GameViewport->GetGameViewport();
#if WITH_EDITOR_AUTOMATION_TESTS
// In the editor we can only attempt to resize a standalone viewport
UWorld* World = GetWorld();
UEditorEngine* EditorEngine = Cast<UEditorEngine>(GEngine);
const bool bIsPIEViewport = GameViewport->IsPlayInEditorViewport();
const bool bIsNewViewport = World && EditorEngine && EditorEngine->WorldIsPIEInNewViewport(World);
bApplyScreenshotSettings = !bIsPIEViewport || bIsNewViewport;
#endif
if (bApplyScreenshotSettings)
{
ScreenshotEnvSetup->Setup(GetWorld(), ScreenshotOptions);
FlushRenderingCommands();
bNeedsViewSettingsRestore = true;
// Some platforms (such as consoles) require fixed width/height
// back-buffers so we cannot adjust the viewport size
if (!FPlatformProperties::HasFixedResolution())
{
ViewportRestoreSize = GameViewport->GetSize();
FIntPoint ScreenshotViewportSize = UAutomationBlueprintFunctionLibrary::GetAutomationScreenshotSize(ScreenshotOptions);
GameViewport->SetViewportSize(ScreenshotViewportSize.X, ScreenshotViewportSize.Y);
bNeedsViewportRestore = true;
}
}
#endif
}
void AScreenshotFunctionalTestBase::OnScreenShotCaptured(int32 InSizeX, int32 InSizeY, const TArray<FColor>& InImageData)
{
check(GEngine->GameViewport);
GEngine->GameViewport->OnScreenshotCaptured().RemoveAll(this);
#if WITH_AUTOMATION_TESTS
TArray<uint8> CapturedFrameTrace = AutomationCommon::CaptureFrameTrace(GetWorld()->GetName(), TestLabel);
FAutomationScreenshotData Data = UAutomationBlueprintFunctionLibrary::BuildScreenshotData(GetWorld()->GetName(), TestLabel, InSizeX, InSizeY);
// Copy the relevant data into the metadata for the screenshot.
Data.bHasComparisonRules = true;
Data.ToleranceRed = ScreenshotOptions.ToleranceAmount.Red;
Data.ToleranceGreen = ScreenshotOptions.ToleranceAmount.Green;
Data.ToleranceBlue = ScreenshotOptions.ToleranceAmount.Blue;
Data.ToleranceAlpha = ScreenshotOptions.ToleranceAmount.Alpha;
Data.ToleranceMinBrightness = ScreenshotOptions.ToleranceAmount.MinBrightness;
Data.ToleranceMaxBrightness = ScreenshotOptions.ToleranceAmount.MaxBrightness;
Data.bIgnoreAntiAliasing = ScreenshotOptions.bIgnoreAntiAliasing;
Data.bIgnoreColors = ScreenshotOptions.bIgnoreColors;
Data.MaximumLocalError = ScreenshotOptions.MaximumLocalError;
Data.MaximumGlobalError = ScreenshotOptions.MaximumGlobalError;
// Add the notes
Data.Notes = Notes;
if (GIsAutomationTesting)
{
FAutomationTestFramework::Get().OnScreenshotCompared.AddUObject(this, &AScreenshotFunctionalTestBase::OnComparisonComplete);
}
FAutomationTestFramework::Get().OnScreenshotAndTraceCaptured().ExecuteIfBound(InImageData, CapturedFrameTrace, Data);
UE_LOG(LogScreenshotFunctionalTest, Log, TEXT("Screenshot captured as %s"), *Data.ScreenshotName);
#endif
}
void AScreenshotFunctionalTestBase::RequestScreenshot()
{
check(IsInGameThread());
check(GEngine->GameViewport);
// Make sure any screenshot request has been processed
FlushRenderingCommands();
UGameViewportClient* GameViewportClient = GEngine->GameViewport;
GameViewportClient->OnScreenshotCaptured().AddUObject(this, &AScreenshotFunctionalTestBase::OnScreenShotCaptured);
}
void AScreenshotFunctionalTestBase::OnComparisonComplete(const FAutomationScreenshotCompareResults& CompareResults)
{
FAutomationTestFramework::Get().OnScreenshotCompared.RemoveAll(this);
if (FAutomationTestBase* CurrentTest = FAutomationTestFramework::Get().GetCurrentTest())
{
CurrentTest->AddEvent(CompareResults.ToAutomationEvent(TestLabel));
}
FAutomationTestFramework::Get().NotifyScreenshotTakenAndCompared();
}
void AScreenshotFunctionalTestBase::RestoreViewSettings()
{
check(GEngine->GameViewport && GEngine->GameViewport->GetGameViewport());
check(IsInGameThread());
#if WITH_AUTOMATION_TESTS
if (bNeedsViewSettingsRestore)
{
ScreenshotEnvSetup->Restore();
}
if (!FPlatformProperties::HasFixedResolution() && bNeedsViewportRestore)
{
FSceneViewport* GameViewport = GEngine->GameViewport->GetGameViewport();
GameViewport->SetViewportSize(ViewportRestoreSize.X, ViewportRestoreSize.Y);
}
#endif
bNeedsViewSettingsRestore = false;
bNeedsViewportRestore = false;
}
#if WITH_EDITOR
bool AScreenshotFunctionalTestBase::CanEditChange(const FProperty* InProperty) const
{
bool bIsEditable = Super::CanEditChange(InProperty);
if (bIsEditable && InProperty)
{
const FName PropertyName = InProperty->GetFName();
if (PropertyName == GET_MEMBER_NAME_CHECKED(FAutomationScreenshotOptions, ToleranceAmount))
{
bIsEditable = ScreenshotOptions.Tolerance == EComparisonTolerance::Custom;
}
else if (PropertyName == TEXT("ObservationPoint"))
{
// You can't ever observe from anywhere but the camera on the screenshot test.
bIsEditable = false;
}
}
return bIsEditable;
}
void AScreenshotFunctionalTestBase::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
if (PropertyChangedEvent.Property)
{
const FName PropertyName = PropertyChangedEvent.Property->GetFName();
if (PropertyName == GET_MEMBER_NAME_CHECKED(FAutomationScreenshotOptions, Tolerance))
{
ScreenshotOptions.SetToleranceAmounts(ScreenshotOptions.Tolerance);
}
}
}
#endif
void AScreenshotFunctionalTestBase::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
Ar.UsingCustomVersion(FAutomationObjectVersion::GUID);
if (Ar.CustomVer(FAutomationObjectVersion::GUID) < FAutomationObjectVersion::DefaultToScreenshotCameraCutAndFixedTonemapping)
{
ScreenshotOptions.bDisableTonemapping = true;
}
}