You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Changes FAssetHeaderPatcherInner to leverage the CoreRedirect system for resolving FNames in a package header, and string paths when context about the string itself is well known (i.e. we know the string data is a stringified ObjectPath/PackagePath, or ObjectName are deducible). We still make use of string scanning replacement mechanism but those are now constrained to only patching strings content specifically (e.g. Tag data)
- Added FAssetHeaderPatcher::FContext for storing data on how to perform a patch (which redirects to follow, string -> string replacement map). Allows for an extensibility point for encapsulating special case patching so we don't need to rely on string->string mappings exclusively - Added `virtual FArchive& operator<<(FTopLevelAssetPath& Value)` to `FActorDescArchive` to allow for patching of FTopLevelAssetPath directly. Without this overload the FNames within a FTopLevelAssetPath would be patched one at a time losing all context about what the FNames are. - Removed IAssetTools::GetAdditionalPatchCopyMappings, GetPatchCopyMappingsForRootRename, and PatchCopyPackageFile as these methods were internal and using the patcher directly should be preferred. - Added some unit tests for the FAssetHeaderPatcherInner implementation works to codify the assumptions and expectations of the patcher implementation New patching changes are left disabled by default #rnx #rb Dave.Belanger, JeanFrancois.Dube [CL 36764489 by kevin macaulayvacher in 5.5 branch]
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tasks/Task.h"
|
||||
#include "Containers/ContainersFwd.h"
|
||||
#include "UObject/CoreRedirects.h"
|
||||
|
||||
/**
|
||||
* Delegate called on when patch operation completes
|
||||
* @param SrcFilePath Path of file being read for patching
|
||||
* @param DstFilePath Path of file being written to after patching
|
||||
*/
|
||||
DECLARE_DELEGATE_TwoParams(FAssetHeaderPatcherCompletionDelegate, const FString& /*SrcFilePath*/, const FString& /*DstFilePath*/)
|
||||
|
||||
UE_INTERNAL struct ASSETTOOLS_API FAssetHeaderPatcher
|
||||
{
|
||||
enum class EResult
|
||||
{
|
||||
NotStarted,
|
||||
Cancelled,
|
||||
InProgress,
|
||||
Success,
|
||||
ErrorFailedToLoadSourceAsset,
|
||||
ErrorFailedToDeserializeSourceAsset,
|
||||
ErrorUnexpectedSectionOrder,
|
||||
ErrorBadOffset,
|
||||
ErrorUnkownSection,
|
||||
ErrorFailedToOpenDestinationFile,
|
||||
ErrorFailedToWriteToDestinationFile,
|
||||
ErrorEmptyRequireSection,
|
||||
};
|
||||
|
||||
UE_INTERNAL struct ASSETTOOLS_API FContext
|
||||
{
|
||||
FContext() = default;
|
||||
|
||||
/**
|
||||
* Context used for patching. Contains all information for how object and package references
|
||||
* will be changed as part of patching.
|
||||
* *
|
||||
* When bInGatherDependentPackages is true, the provided long package name (/Root/Folder/Package) to
|
||||
* destination long package name mapping will be used to find any dependent packages that must also
|
||||
* be patched due to internal references. The mapping provided in InSrcAndDstPackagePaths will be used
|
||||
* to determine the filepath on disk to write when patching.
|
||||
*
|
||||
* @param InSrcAndDstPackagePaths Map of all long package names (/Root/Folder/Package) to be patched and to which new name they should be patched to.
|
||||
* @param bInGatherDependentPackages If true (default), upon creating the context GatherDependentPackages() will be called.
|
||||
**/
|
||||
FContext(const TMap<FString, FString>& InSrcAndDstPackagePaths, const bool bInGatherDependentPackages = true);
|
||||
|
||||
/**
|
||||
* Context used for patching. Contains all information for how object and package references
|
||||
* will be changed as part of patching.
|
||||
*
|
||||
* When patching, package paths to patch will be deduced by the filepath mappings provided in InSrcAndDstFilePaths. All assets
|
||||
* under InSrcRoot will be written as package paths under a mountpoint located at InSrcBaseDir.
|
||||
*
|
||||
* e.g. Path "C:/User/Repo/Project/Content/Skeletons/Player.uasset" -> "/InSrcRoot/Skeletons/Player" when InSrcBaseDir=C:/User/Repo/Project (/Content is assumed internally)
|
||||
*
|
||||
* @param InSrcRoot The root mount point for assets to be patched
|
||||
* @param InDstRoot The new root mount point for patched assets to be placed under
|
||||
* @param InSrcBaseDir Path to the directory holding the /Content/ directory for assets to patch
|
||||
* @param InSrcAndDstFilePaths Map of filepaths for files to be patched and where to write the patched version to
|
||||
* @param InMountPointReplacements Map of root mountpoints (name only, no "/" prefix or suffix) to replace when patching
|
||||
**/
|
||||
FContext(const FString& InSrcRoot, const FString& InDstRoot, const FString& InSrcBaseDir, const TMap<FString, FString>& InSrcAndDstFilePaths, const TMap<FString, FString>& InMountPointReplacements);
|
||||
|
||||
/*
|
||||
* Returns the mapping of source long package names to destination package paths used when patching.
|
||||
* This mapping may include more packages than initially supplied to the FContext
|
||||
* if GatherDependentPackages has already been called.
|
||||
* Note, this map can be invalidated by calls to GatherDependentPackages()
|
||||
*/
|
||||
const TMap<FString, FString>& GetLongPackagePathRemapping() const
|
||||
{
|
||||
return PackagePathRenameMap;
|
||||
};
|
||||
|
||||
protected:
|
||||
friend FAssetHeaderPatcher;
|
||||
|
||||
void AddVerseMounts();
|
||||
void GatherDependentPackages();
|
||||
void GenerateFilePathsFromPackagePaths();
|
||||
void GeneratePackagePathsFromFilePaths(const FString& InSrcRoot, const FString& InDstRoot, const FString& InSrcBaseDir);
|
||||
void GenerateAdditionalRemappings();
|
||||
|
||||
TArray<FString> VerseMountPoints;
|
||||
TMap<FString, FString> PackagePathRenameMap;
|
||||
TMap<FString, FString> FilePathRenameMap;
|
||||
|
||||
// Todo: Make TSet once FCoreRedirect GetTypeHash is implemented
|
||||
TArray<FCoreRedirect> Redirects;
|
||||
|
||||
// String mappings are only used for best-effort replacements. These will be error-prone
|
||||
// and we should strive for more structured data formats to guard against errors here
|
||||
TMap<FString, FString> StringReplacements;
|
||||
TMap<FString, FString> StringMountReplacements;
|
||||
};
|
||||
|
||||
FAssetHeaderPatcher() = default;
|
||||
FAssetHeaderPatcher(FContext InContext) : Context(InContext) { Reset(); }
|
||||
|
||||
/*
|
||||
* Resets the patcher state and sets a new patching context.
|
||||
* It is an error to call while patching is already in progress.
|
||||
*/
|
||||
void SetContext(FContext InContext);
|
||||
|
||||
/*
|
||||
* Schedules the reading of source files determined by the patcher context, as well as the writing of the patched versions
|
||||
* of all source files read.
|
||||
*
|
||||
* @param InOutNumFilesToPatch Optional value to know how many files are expected to be read/written during patching
|
||||
* @param InOutNumFilesPatched Optional value used to know how the patcher is progressing (useful for progress bars)
|
||||
*/
|
||||
UE::Tasks::FTask PatchAsync(int32* InOutNumFilesToPatch = nullptr, int32* InOutNumFilesPatched = nullptr);
|
||||
UE::Tasks::FTask PatchAsync(int32* InOutNumFilesToPatch, int32* InOutNumFilesPatched, FAssetHeaderPatcherCompletionDelegate InOnSuccess, FAssetHeaderPatcherCompletionDelegate InOnError);
|
||||
|
||||
/*
|
||||
* Returns the status of any inflight patching operations. In the case of multiple errors, the last seen error will be reported.
|
||||
* Per file error status codes can be returned with GetErrorFiles().
|
||||
*/
|
||||
EResult GetPatchResult() const
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns source file -> destination mapping for all files that were patched successfully.
|
||||
*/
|
||||
TMap<FString, FString> GetPatchedFiles() const
|
||||
{
|
||||
if (IsPatching())
|
||||
{
|
||||
return TMap<FString, FString>();
|
||||
}
|
||||
|
||||
return PatchedFiles;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the patcher encountered errors (even if patching was cancelled)
|
||||
*/
|
||||
bool HasErrors()
|
||||
{
|
||||
FScopeLock Lock(&ErroredFilesLock);
|
||||
return !!ErroredFiles.Num();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a map of all files that had an error during patching with an error code to provide context as to the cause of the error.
|
||||
*/
|
||||
TMap<FString, EResult> GetErrorFiles()
|
||||
{
|
||||
FScopeLock Lock(&ErroredFilesLock);
|
||||
return ErroredFiles;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the patcher is still in theprocess of patching.
|
||||
*/
|
||||
bool IsPatching() const
|
||||
{
|
||||
return !PatchingTask.IsCompleted();
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancels an in-flight patching operation. Patching work on individual files that has already started will run to completion
|
||||
* however any files that have not started patching will be skipped. Even after cancelling, one must wait for the patcher to complete
|
||||
* by waiting on the GetPatchingTask() explciitly or until IsPatching returns false.
|
||||
*
|
||||
* @return true if an in-flight patching operation was cancelled. If no patching operation is underway, returns false.
|
||||
*/
|
||||
bool CancelPatching()
|
||||
{
|
||||
if (!IsPatching())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bCancelled = true;
|
||||
Status = EResult::Cancelled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the task for all patcher work underway. Waiting on this task will guarantee all patch work is completed.
|
||||
*/
|
||||
UE::Tasks::FTask GetPatchingTask() const
|
||||
{
|
||||
return PatchingTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches object and package references contained within InSrcAsset using the mapping provided to InContext. The
|
||||
* patched asset will be written to InDstAsset.
|
||||
*
|
||||
* @param InSrcAsset Long package name (/Root/Folder/Package) to read in to be patched.
|
||||
* @param InDstAsset Long package name (/Root/Folder/Package) where the patched package will be written to.
|
||||
* @param InContext Context for how the patching will be performed. Contains all remapping information to the patcher.
|
||||
* @return Success patching was successful and the InDstAsset package was written. Returns an error status otherwise.
|
||||
**/
|
||||
static EResult DoPatch(const FString& InSrcAsset, const FString& InDstAsset, const FContext& InContext);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
FContext Context;
|
||||
|
||||
TMap<FString, EResult> ErroredFiles;
|
||||
FCriticalSection ErroredFilesLock;
|
||||
|
||||
TMap<FString, FString> PatchedFiles;
|
||||
|
||||
UE::Tasks::FTask PatchingTask;
|
||||
EResult Status = EResult::NotStarted;
|
||||
std::atomic<bool> bCancelled = false;
|
||||
};
|
||||
UE_INTERNAL ASSETTOOLS_API FString LexToString(FAssetHeaderPatcher::EResult InResult);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tasks/Task.h"
|
||||
#include "Containers/ContainersFwd.h"
|
||||
|
||||
struct FAssetHeaderPatcher
|
||||
{
|
||||
enum class EResult
|
||||
{
|
||||
Success,
|
||||
ErrorFailedToLoadSourceAsset,
|
||||
ErrorFailedToDeserializeSourceAsset,
|
||||
ErrorUnexpectedSectionOrder,
|
||||
ErrorBadOffset,
|
||||
ErrorUnkownSection,
|
||||
ErrorFailedToOpenDestinationFile,
|
||||
ErrorFailedToWriteToDestinationFile,
|
||||
ErrorEmptyRequireSection,
|
||||
};
|
||||
|
||||
static EResult DoPatch(const FString& InSrcAsset, const FString& InDstAsse, const TMap<FString, FString>& InSearchAndReplace, bool bInStarRestrictionInUse = false);
|
||||
|
||||
static EResult Test_DoPatch(FArchive& InSrcReader, FArchive& InDstWriter, const TMap<FString, FString>& InSearchAndReplace);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -134,9 +134,6 @@ public:
|
||||
virtual bool ValidateFlattenedAdvancedCopyDestinations(const TMap<FString, FString>& FlattenedPackagesAndDestinations) const override;
|
||||
virtual void GetAllAdvancedCopySources(FName SelectedPackage, FAdvancedCopyParams& CopyParams, TArray<FName>& OutPackageNamesToCopy, TMap<FName, FName>& DependencyMap, const class UAdvancedCopyCustomization* CopyCustomization) const override;
|
||||
virtual void InitAdvancedCopyFromCopyParams(FAdvancedCopyParams CopyParams) const override;
|
||||
virtual bool PatchCopyPackageFile(const FString& SrcFile, const FString& DstFile, const TMap<FString, FString>& SearchForAndReplace) const override;
|
||||
virtual TMap<FString, FString> GetPatchCopyMappingsForRootRename(const FString& SrcRoot, const FString& DstRoot, const FString& SrcBaseDir, const TArray<TPair<FString, FString>>& SourceAndDestFiles, const TMap<FString, FString>& MountPointReplacements) const override;
|
||||
virtual TMap<FString, FString> GetAdditionalPatchCopyMappings(const TMap<FString, FString>& SourceAndDestPackages) const override;
|
||||
virtual void OpenEditorForAssets(const TArray<UObject*>& Assets) override;
|
||||
virtual void ConvertVirtualTextures(const TArray<UTexture2D*>& Textures, bool bConvertBackToNonVirtual, const TArray<UMaterial*>* RelatedMaterials = nullptr) const override;
|
||||
virtual bool IsAssetClassSupported(const UClass* AssetClass) const override;
|
||||
|
||||
@@ -611,15 +611,6 @@ public:
|
||||
/* Given a complete set of copy parameters, which includes the selected package set, start the advanced copy process */
|
||||
virtual void InitAdvancedCopyFromCopyParams(FAdvancedCopyParams CopyParams) const = 0;
|
||||
|
||||
/** Copies a file, patching internal references without performing a de-serialization. This is a blocking operation. returns true on successful copy */
|
||||
UE_INTERNAL virtual bool PatchCopyPackageFile(const FString& SrcFile, const FString& DstFile, const TMap<FString, FString>& SearchForAndReplace) const = 0;
|
||||
|
||||
/** Generates the PatchCopyPackageFile SearchForAndReplace parameter if all you are doing is changing the root and not the relative path of assets */
|
||||
UE_INTERNAL virtual TMap<FString, FString> GetPatchCopyMappingsForRootRename(const FString& SrcRoot, const FString& DstRoot, const FString& SrcBaseDir, const TArray<TPair<FString, FString>>& SourceAndDestFiles, const TMap<FString, FString>& MountPointReplacements) const = 0;
|
||||
|
||||
/** Generates additional entries for the PatchCopyPackageFile SearchForAndReplace parameter based on the specified package paths mapping */
|
||||
UE_INTERNAL virtual TMap<FString, FString> GetAdditionalPatchCopyMappings(const TMap<FString, FString>& SourceAndDestPackages) const = 0;
|
||||
|
||||
/** Opens editor for assets */
|
||||
UFUNCTION(BlueprintCallable, Category = "Editor Scripting | Asset Tools", meta = (DeprecatedFunction, DeprecationMessage = "Please use UAssetEditorSubsystem::OpenEditorForAssets instead."))
|
||||
virtual void OpenEditorForAssets(const TArray<UObject*>& Assets) = 0;
|
||||
|
||||
Reference in New Issue
Block a user