Files
UnrealEngineUWP/Engine/Source/Developer/FunctionalTesting/Private/ScreenshotFunctionalTestBase.cpp
Chris Bunner d6e57b4ca3 Copying //UE4/Dev-Automation to //UE4/Dev-Main (Source: //UE4/Dev-Automation @ 3792497)
#rb
#lockdown Nick.Penwarden

============================
  MAJOR FEATURES & CHANGES
============================

Change 3776794 by Chris.Bunner

	Fixed inverted check.

Change 3778396 by Chris.Bunner

	By default functional screenshot tests now enable camera cut and a fixed tonemap/exposure.
	Existing tests in PostProcessing have had the FixedTonemapping flag disabled.
	Updated all existing screenshots against the new fixed gamma ground truth.

Change 3778592 by Chris.Bunner

	Updating PostProcess screenshots that managed to collide mid P4 add.

Change 3778793 by Chris.Bunner

	Override the secondary screen percentage (used for high DPI) when taking screenshots. This is necessary for consistent results between machines.

Change 3781715 by Chris.Bunner

	Updating Windows screenshots.

Change 3781717 by Chris.Bunner

	Fixes for eye adaptation and tonemapping override consistency between test types and run modes.

Change 3783199 by Chris.Bunner

	Added separate add/replace screenshot buttons to know if we're working with a matching platform tier or a fallback.

Change 3783228 by Chris.Bunner

	When incoming screenshots are different sizes create a delta of the minimum shared dimensions but still force a failure. The UI is more consistent showing any delta, even if it's almost pure white.

Change 3783712 by Chris.Bunner

	Rebuilt translucency lighting test map and updated screenshot results.

Change 3784010 by Chris.Bunner

	Adding Mac-specific PostProcessing screenshots.

Change 3787456 by Chris.Bunner

	Improving name matching consistency of test blacklist entries.

Change 3787522 by Chris.Bunner

	Updating Mac-specific screenshots.

Change 3787583 by Chris.Bunner

	Updating Mac-Specific screenshots.

Change 3787832 by Chris.Bunner

	Fixing-up NaNs in two saved level's HLOD world settings.

Change 3789147 by Chris.Bunner

	Updating Sequencer sub-levels which still had NaNs in World Settings.

Change 3791454 by Chris.Bunner

	Deleted ancient screenshot re-introduced by Fortnite merge.

Change 3781713 by Chris.Bunner

	Updating platform unique screenshots - Tessellation, fixed vs variable screenshot size, Niagara simulation.

Change 3776756 by Chris.Bunner

	Initial pass at hierarchical screenshot testing.
	Deleted existing platforms automated test screenshots.

Change 3784051 by Chris.Bunner

	Updated CableActor screenshots for new capture defaults.

Change 3787092 by Chris.Bunner

	Added blacklist as "AutomationTestBlacklist" in Engine.ini.
	Formatting fix-up in existing automation test config.
	Removed workaround cvar for physicalized animation tests failing on platforms.

[CL 3792526 by Chris Bunner in Main branch]
2017-12-06 14:51:13 -05:00

238 lines
7.6 KiB
C++

// Copyright 1998-2017 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"
#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_LOG_CATEGORY_STATIC(LogScreenshotFunctionalTest, Log, Log)
AScreenshotFunctionalTestBase::AScreenshotFunctionalTestBase(const FObjectInitializer& ObjectInitializer)
: AFunctionalTest(ObjectInitializer)
, ScreenshotOptions(EComparisonTolerance::Low)
{
ScreenshotCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
ScreenshotCamera->SetupAttachment(RootComponent);
#if (WITH_DEV_AUTOMATION_TESTS || WITH_PERF_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()
{
RestoreGameViewport();
FAutomationTestFramework::Get().OnScreenshotTakenAndCompared.RemoveAll(this);
FinishTest(EFunctionalTestResult::Succeeded, TEXT(""));
}
void AScreenshotFunctionalTestBase::PrepareForScreenshot()
{
check(GEngine->GameViewport && GEngine->GameViewport->GetGameViewport());
check(IsInGameThread());
// PS4 requires fixed with/height for video output back buffers so
// we cannot adjust the size of viewports
if (!FPlatformProperties::HasFixedResolution())
{
FSceneViewport* GameViewport = GEngine->GameViewport->GetGameViewport();
ViewportRestoreSize = GameViewport->GetSize();
FIntPoint ScreenshotViewportSize = UAutomationBlueprintFunctionLibrary::GetAutomationScreenshotSize(ScreenshotOptions);
GameViewport->SetViewportSize(ScreenshotViewportSize.X, ScreenshotViewportSize.Y);
}
#if (WITH_DEV_AUTOMATION_TESTS || WITH_PERF_AUTOMATION_TESTS)
ScreenshotEnvSetup->Setup(ScreenshotOptions);
#endif
FlushRenderingCommands();
}
void AScreenshotFunctionalTestBase::OnScreenShotCaptured(int32 InSizeX, int32 InSizeY, const TArray<FColor>& InImageData)
{
check(GEngine->GameViewport);
GEngine->GameViewport->OnScreenshotCaptured().RemoveAll(this);
#if (WITH_DEV_AUTOMATION_TESTS || WITH_PERF_AUTOMATION_TESTS)
FAutomationScreenshotData Data = AutomationCommon::BuildScreenshotData(GetWorld()->GetName(), GetName(), 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;
if (GIsAutomationTesting)
{
FAutomationTestFramework::Get().OnScreenshotCompared.AddUObject(this, &AScreenshotFunctionalTestBase::OnComparisonComplete);
}
FAutomationTestFramework::Get().OnScreenshotCaptured().ExecuteIfBound(InImageData, Data);
UE_LOG(LogScreenshotFunctionalTest, Log, TEXT("Screenshot captured as %s"), *Data.Path);
#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(bool bWasNew, bool bWasSimilar, double MaxLocalDifference, double GlobalDifference, FString ErrorMessage)
{
FAutomationTestFramework::Get().OnScreenshotCompared.RemoveAll(this);
if (bWasNew)
{
UE_LOG(LogScreenshotFunctionalTest, Warning, TEXT("New Screenshot '%s' was discovered! Please add a ground truth version of it."), *GetName());
}
else
{
if (bWasSimilar)
{
UE_LOG(LogScreenshotFunctionalTest, Display, TEXT("Screenshot '%s' was similar! Global Difference = %f, Max Local Difference = %f"), *GetName(), GlobalDifference, MaxLocalDifference);
}
else
{
if (ErrorMessage.IsEmpty())
{
UE_LOG(LogScreenshotFunctionalTest, Error, TEXT("Screenshot '%s' test failed, Screnshots were different! Global Difference = %f, Max Local Difference = %f"), *GetName(), GlobalDifference, MaxLocalDifference);
}
else
{
UE_LOG(LogScreenshotFunctionalTest, Error, TEXT("Screenshot '%s' test failed; Error = %s"), *GetName(), *ErrorMessage);
}
}
}
FAutomationTestFramework::Get().NotifyScreenshotTakenAndCompared();
}
void AScreenshotFunctionalTestBase::RestoreGameViewport()
{
check(GEngine->GameViewport && GEngine->GameViewport->GetGameViewport());
check(IsInGameThread());
if (!FPlatformProperties::HasFixedResolution())
{
FSceneViewport* GameViewport = GEngine->GameViewport->GetGameViewport();
GameViewport->SetViewportSize(ViewportRestoreSize.X, ViewportRestoreSize.Y);
}
#if (WITH_DEV_AUTOMATION_TESTS || WITH_PERF_AUTOMATION_TESTS)
ScreenshotEnvSetup->Restore();
#endif
}
#if WITH_EDITOR
bool AScreenshotFunctionalTestBase::CanEditChange(const UProperty* 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;
}
}