Files
UnrealEngine/Engine/Source/Developer/FunctionalTesting/Private/GroundTruthData.cpp
2025-05-18 13:04:45 +08:00

135 lines
3.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "GroundTruthData.h"
#include "UObject/UnrealType.h"
#include "UObject/Package.h"
#include "UObject/SavePackage.h"
#include "Misc/PackageName.h"
#include "AssetRegistry/AssetData.h"
#if WITH_EDITOR
#include "ISourceControlModule.h"
#include "ISourceControlProvider.h"
#include "SourceControlOperations.h"
#include "SourceControlHelpers.h"
#endif
#include UE_INLINE_GENERATED_CPP_BY_NAME(GroundTruthData)
DEFINE_LOG_CATEGORY_STATIC(GroundTruthLog, Log, Log)
UGroundTruthData::UGroundTruthData()
: bResetGroundTruth(false)
{
}
bool UGroundTruthData::CanModify() const
{
return ObjectData == nullptr;
}
UObject* UGroundTruthData::LoadObject()
{
UE_LOG(GroundTruthLog, Log, TEXT("Loaded Ground Truth, '%s'."), *GetPathName());
return ObjectData;
}
void UGroundTruthData::SaveObject(UObject* GroundTruth)
{
FAssetData GroundTruthAssetData(this);
UPackage* GroundTruthPackage = GetOutermost();
FString GroundTruthPackageName = GroundTruthAssetData.PackageName.ToString();
#if WITH_EDITOR
if (!CanModify())
{
UE_LOG(GroundTruthLog, Warning, TEXT("Ground Truth, '%s' already set, unable to save changes. Open and use bResetGroundTruth to reset the ground truth."), *GroundTruthPackageName);
return;
}
if (GroundTruth == nullptr)
{
UE_LOG(GroundTruthLog, Error, TEXT("Ground Truth, '%s' can not store a null object."), *GroundTruthPackageName);
return;
}
if (GIsBuildMachine)
{
UE_LOG(GroundTruthLog, Error, TEXT("Ground Truth, '%s' can not be modified on the build machine."), *GroundTruthPackageName);
return;
}
if (ISourceControlModule::Get().IsEnabled())
{
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
SourceControlProvider.Execute(ISourceControlOperation::Create<FMarkForAdd>(), GroundTruthPackage);
SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), GroundTruthPackage);
}
// There is an edge case for Actors where calling `Rename` will transfer ownership from the level to the GroundTruthData and will remove the Actor from the current level
// To avoid any issues this process causes, we want to duplicate our object with a transient package before performing the rename which will change the ownership from the transient package to the GroundTruthData
ObjectData = DuplicateObject(GroundTruth, nullptr);
ObjectData->Rename(nullptr, this, REN_SkipComponentRegWork);
MarkPackageDirty();
FSavePackageArgs SaveArgs;
SaveArgs.TopLevelFlags = RF_Standalone;
SaveArgs.SaveFlags = SAVE_NoError;
if (!UPackage::SavePackage(GroundTruthPackage, nullptr,
*FPackageName::LongPackageNameToFilename(GroundTruthPackageName, FPackageName::GetAssetPackageExtension()),
SaveArgs))
{
UE_LOG(GroundTruthLog, Error, TEXT("Failed to save ground truth data! %s"), *GroundTruthPackageName);
}
UE_LOG(GroundTruthLog, Log, TEXT("Saved Ground Truth, '%s'."), *GroundTruthPackageName);
#else
UE_LOG(GroundTruthLog, Error, TEXT("Can't save ground truth data outside of the editor, '%s'."), *GroundTruthPackageName);
#endif
}
#if WITH_EDITOR
void UGroundTruthData::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UGroundTruthData, bResetGroundTruth))
{
bResetGroundTruth = false;
if (ObjectData)
{
ObjectData->Rename(nullptr, GetTransientPackage());
ObjectData = nullptr;
}
MarkPackageDirty();
}
}
#endif
void UGroundTruthData::ResetObject()
{
#if WITH_EDITOR
if (ObjectData)
{
ObjectData->Rename(nullptr, GetTransientPackage());
ObjectData = nullptr;
MarkPackageDirty();
}
#else
FAssetData GroundTruthAssetData(this);
FString GroundTruthPackageName = GroundTruthAssetData.PackageName.ToString();
UE_LOG(GroundTruthLog, Error, TEXT("Can't reset ground truth data outside of the editor, '%s'."), *GroundTruthPackageName);
#endif
}