You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2716841 on 2015/10/05 by Mike.Beach (WIP) Cleaning up how we setup script assets for replacement on cook (aligning more with the Blueprint conversion tool). #codereview Maciej.Mroz Change 2719089 on 2015/10/07 by Maciej.Mroz ToValidCPPIdentifierChars handles propertly '?' char. #codereview Dan.Oconnor Change 2719361 on 2015/10/07 by Maciej.Mroz Generated native code for AnimBPGC - some preliminary changes. Refactor: UAnimBlueprintGeneratedClass is not accessed directly in runtime. It is accessed via UAnimClassInterface interface. Properties USkeletalMeshComponent::AnimBlueprintGeneratedClass and UInterpTrackFloatAnimBPParam::AnimBlueprintClass were changed into "TSubclassOf<UAnimInstance> AnimClass" The UDynamicClass also can deliver the IAnimClassInterface interface. See UAnimClassData, IAnimClassInterface::GetFromClass and UDynamicClass::AnimClassImplementation. #codereview Lina.Halper, Thomas.Sarkanen Change 2719383 on 2015/10/07 by Maciej.Mroz Debug-only code removed Change 2720528 on 2015/10/07 by Dan.Oconnor Fix for determinsitc cooking of async tasks and load asset nodes #codereview Mike.Beach, Maciej.Mroz Change 2721273 on 2015/10/08 by Maciej.Mroz Blueprint Compiler Cpp Backend - Anim Blueprints can be converted - Various fixes/improvements Change 2721310 on 2015/10/08 by Maciej.Mroz refactor (cl#2719361) - no "auto" keyword Change 2721727 on 2015/10/08 by Mike.Beach (WIP) Setup the cook commandlet so it handles converted assets, replacing them with generated classes. - Refactored the conversion manifest (using a map over an array) - Centralized destination paths into a helper struct (for the manifest) - Generating an Editor module that automatically hooks into the cook process when enabled - Loading and applying native replacments for the cook Change 2723276 on 2015/10/09 by Michael.Schoell Blueprints duplicated for PIE will no longer register as dependencies to other Blueprint. #jira UE-16695 - Editor freezes then crashes while attempting to save during PIE #jira UE-21614 - [CrashReport] Crash while saving during PIE - FKismetEditorUtilities::CompileBlueprint() kismet2.cpp:736 Change 2724345 on 2015/10/11 by Ben.Cosh Blueprint profiler at first pass, this includes the ability to instrument specific blueprints with realtime editor stat display. #UEBP-21 - Profiling data capture and storage #UEBP-13 - Performance capture landing page #Branch UE4 #Proj BlueprintProfiler, BlueprintGraph, EditorStyle, Kismet, UnrealEd, CoreUObject, Engine Change 2724613 on 2015/10/12 by Ben.Cosh Incremental update for blueprint profiler to fix the way some of the reported stats cascade through events and branches and additionally some missed bits of code are refactored/removed. #Branch UE4 #Proj BlueprintProfiler #info Whilst looking into this I spotted the reason why the stats seem so erratic, There appears to be an issue with FText's use of EXPERIMENTAL_TEXT_FAST_DECIMAL_FORMAT which I have reported, but ideally disable this locally until a fix is integrated. Change 2724723 on 2015/10/12 by Maciej.Mroz Constructor of a dynamic class creates CDO. #codereview Robert.Manuszewski Change 2725108 on 2015/10/12 by Mike.Beach [UE-21891] Minor fix to the array shuffle() function; now processes the last entry like all the others. Change 2726358 on 2015/10/13 by Maciej.Mroz UDataTable is properly saved even if its RowStruct is null. https://udn.unrealengine.com/questions/264064/crash-using-hotreload-in-custom-datatable-cdo-clas.html Change 2727395 on 2015/10/13 by Mike.Beach (WIP) Second pass on the Blueprint conversion pipeline; setting it up for more optimal (speedier) performance. * Using stubs for replacements (rather than loading dynamic replacement). * Giving the cook commandlet more control (so a conversion could be ran directly). * Now logging replacements by old object path (to account for UPackage replacement queries). * Fix for [UE-21947], unshelved from CL 2724944 (by Maciej.Mroz). #codereview Maciej.Mroz Change 2727484 on 2015/10/13 by Mike.Beach [UE-22008] Fixing up comment/tooltip typo for UActorComponent::bAutoActivate. Change 2727527 on 2015/10/13 by Mike.Beach Downgrading an inactionable EdGraph warning, while adding more info so we could possibly determine what's happening. Change 2727702 on 2015/10/13 by Dan.Oconnor Fix for crash in UDelegateProperty::GetCPPType when called on a function with no OwnerClass (events) Change 2727968 on 2015/10/14 by Maciej.Mroz Since ConstructorHelpers::FClassFinder is usually static, the loaded class should be in root set, to prevent the pointer stored in ConstructorHelpers::FClassFinder from being obsolete. FindOrLoadClass behaves now like FindOrLoadObject. #codereview Robert.Manuszewski, Nick.Whiting Change 2728139 on 2015/10/14 by Phillip.Kavan
656 lines
26 KiB
C++
656 lines
26 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BlueprintNativeCodeGenPCH.h"
|
|
|
|
#include "App.h" // for GetGameName()
|
|
#include "BlueprintNativeCodeGenManifest.h"
|
|
#include "BlueprintNativeCodeGenModule.h"
|
|
#include "IBlueprintCompilerCppBackendModule.h" // for ConstructBaseFilename()
|
|
#include "Engine/Blueprint.h" // for GeneratedClass
|
|
#include "JsonObjectConverter.h"
|
|
#include "NativeCodeGenCommandlineParams.h"
|
|
#include "Serialization/JsonReader.h"
|
|
#include "Serialization/JsonSerializer.h"
|
|
#include "Serialization/JsonWriter.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogNativeCodeGenManifest, Log, All);
|
|
|
|
/*******************************************************************************
|
|
* BlueprintNativeCodeGenManifestImpl
|
|
******************************************************************************/
|
|
|
|
namespace BlueprintNativeCodeGenManifestImpl
|
|
{
|
|
static const int64 CPF_NoFlags = 0x00;
|
|
static const FString ManifestFileExt = TEXT(".BpCodeGenManifest.json");
|
|
static const FString CppFileExt = TEXT(".cpp");
|
|
static const FString HeaderFileExt = TEXT(".h");
|
|
static const FString HeaderSubDir = TEXT("Public");
|
|
static const FString CppSubDir = TEXT("Private");
|
|
static const FString ModuleBuildFileExt = TEXT(".Build.cs");
|
|
static const FString FallbackPluginName = TEXT("NativizedScript");
|
|
static const FString PreviewFilePostfix = TEXT("-Preview");
|
|
static const FString PluginFileExt = TEXT(".uplugin");
|
|
static const FString SourceSubDir = TEXT("Source");
|
|
static const FString EditorModulePostfix = TEXT("Editor");
|
|
|
|
/**
|
|
* Populates the provided manifest object with data from the specified file.
|
|
*
|
|
* @param FilePath A json file path, denoting the file you want loaded and serialized in.
|
|
* @param Manifest The target object that you want filled out with data from the file.
|
|
* @return True if the manifest was successfully loaded, otherwise false.
|
|
*/
|
|
static bool LoadManifest(const FString& FilePath, FBlueprintNativeCodeGenManifest* Manifest);
|
|
|
|
/**
|
|
* Helper function that homogenizes file/directory paths so that they can be
|
|
* compared for equivalence against others.
|
|
*
|
|
* @param DirectoryPath The path that you want sanitized.
|
|
* @return A equivalent file/directory path, standardized for comparisons.
|
|
*/
|
|
static FString GetComparibleDirPath(const FString& DirectoryPath);
|
|
|
|
/**
|
|
* Retrieves the sub-directory for either header or cpp source files
|
|
* (depending on which was requested).
|
|
*
|
|
* @param SourceType Defines the type of source file to return for (header or cpp).
|
|
* @return A directory name for the specified source file type.
|
|
*/
|
|
static const FString& GetSourceSubDir(const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType);
|
|
|
|
/**
|
|
* Retrieves the extension for either header or cpp source files (depending
|
|
* on which was requested).
|
|
*
|
|
* @param SourceType Defines the type of source file to return for (header or cpp).
|
|
* @return A file extension (including the leading dot), for the specified source file type.
|
|
*/
|
|
static const FString& GetSourceFileExt(const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType);
|
|
|
|
/**
|
|
* Constructs a source file path for the specified asset.
|
|
*
|
|
* @param TargetPaths Specified the destination directory for the file.
|
|
* @param Asset The asset you want a header file for.
|
|
* @param SourceType Defines the type of source file to generate for (header or cpp).
|
|
* @return A target file path for the specified asset to save a header to.
|
|
*/
|
|
static FString GenerateSourceFileSavePath(const FBlueprintNativeCodeGenPaths& TargetPaths, const FAssetData& Asset, const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType);
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @param TargetPaths
|
|
* @param Asset
|
|
* @return
|
|
*/
|
|
static FString GenerateUnconvertedWrapperPath(const FBlueprintNativeCodeGenPaths& TargetPaths, const FAssetData& Asset);
|
|
|
|
/**
|
|
* Coordinates with the code-gen backend, to produce a base filename (one
|
|
* without a file extension).
|
|
*
|
|
* @param Asset The asset you want a filename for.
|
|
* @return A filename (without extension) that matches the #include statements generated by the backend.
|
|
*/
|
|
static FString GetBaseFilename(const FAssetData& Asset);
|
|
|
|
/**
|
|
* Collects native packages (which reflect distinct modules) that the
|
|
* specified object relies upon.
|
|
*
|
|
* @param AssetObj The object you want dependencies for.
|
|
* @param DependenciesOut An output array, which will be filled out with module packages that the target object relies upon.
|
|
* @return False if the function failed to collect dependencies for the specified object.
|
|
*/
|
|
static bool GatherModuleDependencies(const UObject* AssetObj, TArray<UPackage*>& DependenciesOut);
|
|
|
|
/**
|
|
* Obtains the reflected name for the native field (class/enum/struct) that
|
|
* we'll generate to replace the specified asset.
|
|
*
|
|
* @param Asset The asset you want a name from.
|
|
* @return The name of the asset field (class/enum/struct).
|
|
*/
|
|
static FString GetFieldName(const FAssetData& Asset);
|
|
|
|
/**
|
|
* The object returned by FAssetData::GetAsset() doesn't always give us the
|
|
* target object that will be replaced (for Blueprint's, it would be the
|
|
* class instead). So this helper function will suss out the right object
|
|
* for you.
|
|
*
|
|
* @param Asset The asset you want an object for.
|
|
* @return A pointer to the targeted object from the asset's package.
|
|
*/
|
|
static UField* GetTargetAssetObject(const FAssetData& Asset);
|
|
|
|
/**
|
|
* Returns the object path for the field from the specified asset's package
|
|
* that is being replaced (Asset.ObjectPath will not suffice, as that
|
|
* does not always reflect the object that is being replaced).
|
|
*
|
|
* @param Asset The asset you want an object-path for.
|
|
* @return An object-path for the target field-object within the asset's package.
|
|
*/
|
|
static FString GetTargetObjectPath(const FAssetData& Asset);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenManifestImpl::LoadManifest(const FString& FilePath, FBlueprintNativeCodeGenManifest* Manifest)
|
|
{
|
|
FString ManifestStr;
|
|
if (FFileHelper::LoadFileToString(ManifestStr, *FilePath))
|
|
{
|
|
TSharedRef< TJsonReader<> > JsonReader = TJsonReaderFactory<>::Create(ManifestStr);
|
|
|
|
TSharedPtr<FJsonObject> JsonObject;
|
|
if (FJsonSerializer::Deserialize(JsonReader, JsonObject))
|
|
{
|
|
return FJsonObjectConverter::JsonObjectToUStruct<FBlueprintNativeCodeGenManifest>(JsonObject.ToSharedRef(), Manifest,
|
|
/*CheckFlags =*/CPF_NoFlags, /*SkipFlags =*/CPF_NoFlags);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static const FString& BlueprintNativeCodeGenManifestImpl::GetSourceSubDir(const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType)
|
|
{
|
|
return (SourceType == FBlueprintNativeCodeGenPaths::HFile) ? HeaderSubDir : CppSubDir;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static const FString& BlueprintNativeCodeGenManifestImpl::GetSourceFileExt(const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType)
|
|
{
|
|
return (SourceType == FBlueprintNativeCodeGenPaths::HFile) ? HeaderFileExt : CppFileExt;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GenerateSourceFileSavePath(const FBlueprintNativeCodeGenPaths& TargetPaths, const FAssetData& Asset, const FBlueprintNativeCodeGenPaths::ESourceFileType SourceType)
|
|
{
|
|
return FPaths::Combine(*TargetPaths.RuntimeSourceDir(SourceType), *GetBaseFilename(Asset)) + GetSourceFileExt(SourceType);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GenerateUnconvertedWrapperPath(const FBlueprintNativeCodeGenPaths& TargetPaths, const FAssetData& Asset)
|
|
{
|
|
const FBlueprintNativeCodeGenPaths::ESourceFileType WrapperFileType = FBlueprintNativeCodeGenPaths::HFile;
|
|
return FPaths::Combine(*TargetPaths.RuntimeSourceDir(WrapperFileType), *GetBaseFilename(Asset)) + GetSourceFileExt(WrapperFileType);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GetBaseFilename(const FAssetData& Asset)
|
|
{
|
|
IBlueprintCompilerCppBackendModule& CodeGenBackend = (IBlueprintCompilerCppBackendModule&)IBlueprintCompilerCppBackendModule::Get();
|
|
return CodeGenBackend.ConstructBaseFilename(Asset.GetAsset());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GetComparibleDirPath(const FString& DirectoryPath)
|
|
{
|
|
FString NormalizedPath = DirectoryPath;
|
|
|
|
const FString PathDelim = TEXT("/");
|
|
if (!NormalizedPath.EndsWith(PathDelim))
|
|
{
|
|
// to account for the case where the relative path would resolve to X:
|
|
// (when we want "X:/")... ConvertRelativePathToFull() leaves the
|
|
// trailing slash, and NormalizeDirectoryName() will remove it (if it is
|
|
// not a drive letter)
|
|
NormalizedPath += PathDelim;
|
|
}
|
|
|
|
if (FPaths::IsRelative(NormalizedPath))
|
|
{
|
|
NormalizedPath = FPaths::ConvertRelativePathToFull(NormalizedPath);
|
|
}
|
|
FPaths::NormalizeDirectoryName(NormalizedPath);
|
|
return NormalizedPath;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenManifestImpl::GatherModuleDependencies(const UObject* AssetObj, TArray<UPackage*>& DependenciesOut)
|
|
{
|
|
UPackage* AssetPackage = AssetObj->GetOutermost();
|
|
|
|
const FLinkerLoad* PkgLinker = FLinkerLoad::FindExistingLinkerForPackage(AssetPackage);
|
|
const bool bFoundLinker = (PkgLinker != nullptr);
|
|
|
|
if (ensure(bFoundLinker))
|
|
{
|
|
for (const FObjectImport& PkgImport : PkgLinker->ImportMap)
|
|
{
|
|
if (PkgImport.ClassName != NAME_Package)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
UPackage* DependentPackage = FindObject<UPackage>(/*Outer =*/nullptr, *PkgImport.ObjectName.ToString(), /*ExactClass =*/true);
|
|
if (DependentPackage == nullptr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// we want only native packages, ones that are not editor-only
|
|
if ((DependentPackage->GetPackageFlags() & (PKG_CompiledIn | PKG_EditorOnly | PKG_Developer)) == PKG_CompiledIn)
|
|
{
|
|
DependenciesOut.AddUnique(DependentPackage);// PkgImport.ObjectName.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
return bFoundLinker;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GetFieldName(const FAssetData& Asset)
|
|
{
|
|
UField* AssetField = GetTargetAssetObject(Asset);
|
|
return (AssetField != nullptr) ? AssetField->GetName() : TEXT("");
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static UField* BlueprintNativeCodeGenManifestImpl::GetTargetAssetObject(const FAssetData& Asset)
|
|
{
|
|
UObject* AssetObj = Asset.GetAsset();
|
|
|
|
UField* AssetField = nullptr;
|
|
if (UBlueprint* BlueprintAsset = Cast<UBlueprint>(AssetObj))
|
|
{
|
|
AssetField = BlueprintAsset->GeneratedClass;
|
|
if (!AssetField)
|
|
{
|
|
UE_LOG(LogNativeCodeGenManifest, Warning, TEXT("null BPGC in %s"), *BlueprintAsset->GetPathName());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// only other asset types that we should be converting are enums and
|
|
// structs (both UFields)
|
|
AssetField = CastChecked<UField>(AssetObj);
|
|
}
|
|
|
|
return AssetField;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static FString BlueprintNativeCodeGenManifestImpl::GetTargetObjectPath(const FAssetData& Asset)
|
|
{
|
|
UField* AssetField = GetTargetAssetObject(Asset);
|
|
return (AssetField != nullptr) ? AssetField->GetPathName() : TEXT("");
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FConvertedAssetRecord
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
FConvertedAssetRecord::FConvertedAssetRecord(const FAssetData& AssetInfo, const FBlueprintNativeCodeGenPaths& TargetPaths)
|
|
: AssetType(AssetInfo.GetClass())
|
|
, TargetObjPath(BlueprintNativeCodeGenManifestImpl::GetTargetObjectPath(AssetInfo))
|
|
{
|
|
GeneratedCppPath = BlueprintNativeCodeGenManifestImpl::GenerateSourceFileSavePath(TargetPaths, AssetInfo, FBlueprintNativeCodeGenPaths::CppFile);
|
|
GeneratedHeaderPath = BlueprintNativeCodeGenManifestImpl::GenerateSourceFileSavePath(TargetPaths, AssetInfo, FBlueprintNativeCodeGenPaths::HFile);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FConvertedAssetRecord::IsValid()
|
|
{
|
|
// every conversion will have a header file (interfaces don't have implementation files)
|
|
return ToAssetRef().IsValid() && (AssetType != nullptr) && !GeneratedHeaderPath.IsEmpty();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FStringAssetReference FConvertedAssetRecord::ToAssetRef() const
|
|
{
|
|
return FStringAssetReference(TargetObjPath);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FUnconvertedDependencyRecord
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
FUnconvertedDependencyRecord::FUnconvertedDependencyRecord(const FAssetData& AssetInfo, const FBlueprintNativeCodeGenPaths& TargetPaths)
|
|
: GeneratedWrapperPath(BlueprintNativeCodeGenManifestImpl::GenerateUnconvertedWrapperPath(TargetPaths, AssetInfo))
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FUnconvertedDependencyRecord::IsValid()
|
|
{
|
|
return !GeneratedWrapperPath.IsEmpty();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FBlueprintNativeCodeGenPaths
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::GetDefaultManifestPath()
|
|
{
|
|
return FApp::GetGameName() + BlueprintNativeCodeGenManifestImpl::ManifestFileExt;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenPaths::FBlueprintNativeCodeGenPaths(const FString& PluginNameIn, const FString& TargetDirIn, const FString& ManifestPathIn)
|
|
: TargetDir(TargetDirIn)
|
|
, PluginName(PluginNameIn)
|
|
, ManifestPath(ManifestPathIn)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::ManifestFilePath() const
|
|
{
|
|
return ManifestPath;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::PluginRootDir() const
|
|
{
|
|
return TargetDir;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::PluginFilePath() const
|
|
{
|
|
return FPaths::Combine(*PluginRootDir(), *PluginName) + BlueprintNativeCodeGenManifestImpl::PluginFileExt;;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::PluginSourceDir() const
|
|
{
|
|
return FPaths::Combine(*PluginRootDir(), *BlueprintNativeCodeGenManifestImpl::SourceSubDir);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimeModuleDir() const
|
|
{
|
|
return FPaths::Combine(*PluginSourceDir(), *RuntimeModuleName());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimeModuleName() const
|
|
{
|
|
return PluginName;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimeBuildFile() const
|
|
{
|
|
return FPaths::Combine(*RuntimeModuleDir(), *RuntimeModuleName()) + BlueprintNativeCodeGenManifestImpl::ModuleBuildFileExt;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimeSourceDir(ESourceFileType SourceType) const
|
|
{
|
|
return FPaths::Combine(*RuntimeModuleDir(), *BlueprintNativeCodeGenManifestImpl::GetSourceSubDir(SourceType));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimeModuleFile(ESourceFileType SourceType) const
|
|
{
|
|
return FPaths::Combine(*RuntimeSourceDir(SourceType), *RuntimeModuleName()) + BlueprintNativeCodeGenManifestImpl::GetSourceFileExt(SourceType);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenPaths::RuntimePCHFilename() const
|
|
{
|
|
return FPaths::GetCleanFilename(RuntimeModuleFile(HFile));
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FBlueprintNativeCodeGenManifest
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenManifest::FBlueprintNativeCodeGenManifest()
|
|
: OutputDir(FPaths::ConvertRelativePathToFull( FPaths::Combine(*FPaths::Combine(*FPaths::GameIntermediateDir(), TEXT("Plugins")), *BlueprintNativeCodeGenManifestImpl::FallbackPluginName) ))
|
|
{
|
|
PluginName = FPaths::GetBaseFilename(OutputDir);
|
|
ManifestFilePath = FPaths::Combine(*GetTargetDir(), *FBlueprintNativeCodeGenPaths::GetDefaultManifestPath());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenManifest::FBlueprintNativeCodeGenManifest(const FNativeCodeGenCommandlineParams& CommandlineParams)
|
|
{
|
|
using namespace BlueprintNativeCodeGenManifestImpl;
|
|
bool const bLoadExistingManifest = !CommandlineParams.bWipeRequested || CommandlineParams.OutputDir.IsEmpty();
|
|
|
|
PluginName = CommandlineParams.PluginName;
|
|
OutputDir = CommandlineParams.OutputDir;
|
|
if (FPaths::IsRelative(OutputDir))
|
|
{
|
|
FPaths::MakePathRelativeTo(OutputDir, *FPaths::GameDir());
|
|
}
|
|
|
|
if (!CommandlineParams.ManifestFilePath.IsEmpty())
|
|
{
|
|
ManifestFilePath = CommandlineParams.ManifestFilePath;
|
|
}
|
|
else
|
|
{
|
|
if (!ensure(!PluginName.IsEmpty()))
|
|
{
|
|
PluginName = FallbackPluginName;
|
|
}
|
|
if (!ensure(!OutputDir.IsEmpty()))
|
|
{
|
|
OutputDir = FPaths::Combine(*FPaths::GameIntermediateDir(), *PluginName);
|
|
}
|
|
|
|
FString ManifestFilename = FBlueprintNativeCodeGenPaths::GetDefaultManifestPath();
|
|
if (CommandlineParams.bPreviewRequested)
|
|
{
|
|
ManifestFilename.InsertAt(ManifestFilename.Find(ManifestFileExt, ESearchCase::CaseSensitive, ESearchDir::FromEnd), PreviewFilePostfix);
|
|
}
|
|
ManifestFilePath = FPaths::Combine(*GetTargetDir(), *ManifestFilename);
|
|
}
|
|
|
|
// incorporate an existing manifest (in case we're only re-converting a
|
|
// handful of assets and adding them into an existing module)
|
|
if (bLoadExistingManifest && LoadManifest(ManifestFilePath, this))
|
|
{
|
|
// if they specified a separate plugin path, lets make sure we use that
|
|
// over what was found in the existing manifest
|
|
if (!CommandlineParams.OutputDir.IsEmpty())
|
|
{
|
|
if (CommandlineParams.bWipeRequested)
|
|
{
|
|
OutputDir = CommandlineParams.OutputDir;
|
|
}
|
|
else
|
|
{
|
|
const FString ExpectedPath = GetComparibleDirPath(CommandlineParams.OutputDir);
|
|
|
|
FString TargetPath = GetTargetDir();
|
|
TargetPath = GetComparibleDirPath(TargetPath);
|
|
|
|
if ( !FPaths::IsSamePath(ExpectedPath, TargetPath) )
|
|
{
|
|
UE_LOG(LogNativeCodeGenManifest, Error,
|
|
TEXT("The existing manifest's plugin path does not match what was specified via the commandline."));
|
|
}
|
|
}
|
|
}
|
|
|
|
const bool bNewPluginNameRequested = !CommandlineParams.PluginName.IsEmpty() && (CommandlineParams.PluginName != PluginName);
|
|
if (bNewPluginNameRequested && !CommandlineParams.bPreviewRequested)
|
|
{
|
|
// delete the old plugin file (if one exists)
|
|
IFileManager::Get().Delete(*GetTargetPaths().PluginFilePath());
|
|
}
|
|
|
|
// if we were only interested in obtaining the plugin path
|
|
if (CommandlineParams.bWipeRequested)
|
|
{
|
|
PluginName = CommandlineParams.PluginName;
|
|
Clear();
|
|
}
|
|
else
|
|
{
|
|
if (bNewPluginNameRequested)
|
|
{
|
|
UE_LOG(LogNativeCodeGenManifest, Warning, TEXT("The specified plugin name (%s) doesn't match the existing one (%s). Overridding with the new name."),
|
|
*CommandlineParams.PluginName, *PluginName);
|
|
PluginName = CommandlineParams.PluginName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenManifest::FBlueprintNativeCodeGenManifest(const FString& ManifestFilePathIn)
|
|
: ManifestFilePath(ManifestFilePathIn)
|
|
{
|
|
BlueprintNativeCodeGenManifestImpl::LoadManifest(ManifestFilePathIn, this);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenPaths FBlueprintNativeCodeGenManifest::GetTargetPaths() const
|
|
{
|
|
return FBlueprintNativeCodeGenPaths(PluginName, GetTargetDir(), ManifestFilePath);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FConvertedAssetRecord& FBlueprintNativeCodeGenManifest::CreateConversionRecord(const FAssetId Key, const FAssetData& AssetInfo)
|
|
{
|
|
const FBlueprintNativeCodeGenPaths TargetPaths = GetTargetPaths();
|
|
|
|
UClass* AssetType = AssetInfo.GetClass();
|
|
// load the asset (if it isn't already)
|
|
const UObject* AssetObj = AssetInfo.GetAsset();
|
|
|
|
FConvertedAssetRecord* ConversionRecordPtr = ConvertedAssets.Find(Key);
|
|
if (ConversionRecordPtr == nullptr)
|
|
{
|
|
UnconvertedDependencies.Remove(Key);
|
|
ConversionRecordPtr = &ConvertedAssets.Add(Key, FConvertedAssetRecord(AssetInfo, TargetPaths));
|
|
}
|
|
else if (!ensure(AssetType == ConversionRecordPtr->AssetType))
|
|
{
|
|
UE_LOG(LogNativeCodeGenManifest, Warning, TEXT("Existing manifest entry for '%s' has a different type, overriding with: '%s'"),
|
|
*AssetInfo.ObjectPath.ToString(), *AssetType->GetName());
|
|
|
|
ConversionRecordPtr->AssetType = AssetType;
|
|
ConversionRecordPtr->TargetObjPath = BlueprintNativeCodeGenManifestImpl::GetTargetObjectPath(AssetInfo);
|
|
}
|
|
|
|
FConvertedAssetRecord& ConversionRecord = *ConversionRecordPtr;
|
|
if (!ConversionRecord.IsValid())
|
|
{
|
|
if (ConversionRecord.GeneratedHeaderPath.IsEmpty())
|
|
{
|
|
ConversionRecord.GeneratedCppPath = BlueprintNativeCodeGenManifestImpl::GenerateSourceFileSavePath(TargetPaths, AssetInfo, FBlueprintNativeCodeGenPaths::CppFile);
|
|
ConversionRecord.GeneratedHeaderPath = BlueprintNativeCodeGenManifestImpl::GenerateSourceFileSavePath(TargetPaths, AssetInfo, FBlueprintNativeCodeGenPaths::HFile);
|
|
}
|
|
ensure(ConversionRecord.IsValid());
|
|
}
|
|
|
|
return ConversionRecord;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FUnconvertedDependencyRecord& FBlueprintNativeCodeGenManifest::CreateUnconvertedDependencyRecord(const FAssetId UnconvertedAssetKey, const FAssetData& AssetInfo, const FAssetId ReferencingAsset)
|
|
{
|
|
FUnconvertedDependencyRecord* RecordPtr = UnconvertedDependencies.Find(UnconvertedAssetKey);
|
|
if (RecordPtr == nullptr)
|
|
{
|
|
const FBlueprintNativeCodeGenPaths TargetPaths = GetTargetPaths();
|
|
RecordPtr = &UnconvertedDependencies.Add(UnconvertedAssetKey, FUnconvertedDependencyRecord(AssetInfo, TargetPaths));
|
|
}
|
|
check(RecordPtr != nullptr);
|
|
|
|
FUnconvertedDependencyRecord& DependencyRecord = *RecordPtr;
|
|
if (!DependencyRecord.IsValid())
|
|
{
|
|
const FBlueprintNativeCodeGenPaths TargetPaths = GetTargetPaths();
|
|
DependencyRecord.GeneratedWrapperPath = BlueprintNativeCodeGenManifestImpl::GenerateUnconvertedWrapperPath(TargetPaths, AssetInfo);
|
|
|
|
ensure(DependencyRecord.IsValid());
|
|
}
|
|
|
|
DependencyRecord.ReferencedBy.AddUnique(ReferencingAsset);
|
|
return DependencyRecord;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
const FConvertedAssetRecord* FBlueprintNativeCodeGenManifest::FindConversionRecord(const FAssetId AssetId) const
|
|
{
|
|
return ConvertedAssets.Find(AssetId);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void FBlueprintNativeCodeGenManifest::GatherModuleDependencies(UPackage* Package)
|
|
{
|
|
BlueprintNativeCodeGenManifestImpl::GatherModuleDependencies(Package, ModuleDependencies);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FBlueprintNativeCodeGenManifest::Save() const
|
|
{
|
|
return SaveAs(*ManifestFilePath);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FBlueprintNativeCodeGenManifest::SaveAs(const TCHAR* Filename) const
|
|
{
|
|
TSharedRef<FJsonObject> JsonObject = MakeShareable(new FJsonObject());
|
|
|
|
if (FJsonObjectConverter::UStructToJsonObject(FBlueprintNativeCodeGenManifest::StaticStruct(), this, JsonObject,
|
|
/*CheckFlags =*/BlueprintNativeCodeGenManifestImpl::CPF_NoFlags, /*SkipFlags =*/BlueprintNativeCodeGenManifestImpl::CPF_NoFlags))
|
|
{
|
|
FString FileContents;
|
|
TSharedRef< TJsonWriter<> > JsonWriter = TJsonWriterFactory<>::Create(&FileContents);
|
|
|
|
if (FJsonSerializer::Serialize(JsonObject, JsonWriter))
|
|
{
|
|
JsonWriter->Close();
|
|
return FFileHelper::SaveStringToFile(FileContents, Filename);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void FBlueprintNativeCodeGenManifest::Merge(const TCHAR* Filename)
|
|
{
|
|
FBlueprintNativeCodeGenManifest OtherManifest = FBlueprintNativeCodeGenManifest(FString(Filename));
|
|
for (auto& Entry : OtherManifest.ModuleDependencies)
|
|
{
|
|
ModuleDependencies.AddUnique(Entry);
|
|
}
|
|
|
|
for (auto& Entry : OtherManifest.ConvertedAssets)
|
|
{
|
|
ConvertedAssets.Add(Entry.Key, Entry.Value);
|
|
}
|
|
|
|
for (auto& Entry : UnconvertedDependencies)
|
|
{
|
|
OtherManifest.UnconvertedDependencies.Add(Entry.Key, Entry.Value);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FString FBlueprintNativeCodeGenManifest::GetTargetDir() const
|
|
{
|
|
FString TargetPath = OutputDir;
|
|
if (FPaths::IsRelative(TargetPath))
|
|
{
|
|
TargetPath = FPaths::ConvertRelativePathToFull(FPaths::GameDir(), TargetPath);
|
|
TargetPath = FPaths::ConvertRelativePathToFull(TargetPath);
|
|
}
|
|
return TargetPath;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void FBlueprintNativeCodeGenManifest::Clear()
|
|
{
|
|
ConvertedAssets.Empty();
|
|
}
|