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
392 lines
14 KiB
C++
392 lines
14 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BlueprintNativeCodeGenPCH.h"
|
|
#include "BlueprintNativeCodeGenManifest.h"
|
|
#include "BlueprintNativeCodeGenUtils.h"
|
|
#include "NativeCodeGenCommandlineParams.h"
|
|
#include "Kismet2/KismetReinstanceUtilities.h" // for FBlueprintCompileReinstancer
|
|
#include "Kismet2/CompilerResultsLog.h"
|
|
#include "KismetCompilerModule.h"
|
|
#include "Engine/Blueprint.h"
|
|
#include "Engine/UserDefinedStruct.h"
|
|
#include "Engine/UserDefinedEnum.h"
|
|
#include "Kismet2/KismetEditorUtilities.h" // for CompileBlueprint()
|
|
#include "OutputDevice.h" // for GWarn
|
|
#include "GameProjectUtils.h" // for GenerateGameModuleBuildFile
|
|
#include "Editor/GameProjectGeneration/Public/GameProjectUtils.h" // for GenerateGameModuleBuildFile()
|
|
#include "App.h" // for GetGameName()
|
|
#include "BlueprintSupport.h" // for FReplaceCookedBPGC
|
|
#include "IBlueprintCompilerCppBackendModule.h" // for OnPCHFilenameQuery()
|
|
#include "BlueprintNativeCodeGenModule.h"
|
|
#include "ScopeExit.h"
|
|
#include "Editor/Kismet/Public/FindInBlueprintManager.h" // for FDisableGatheringDataOnScope
|
|
#include "Editor/UnrealEd/Public/Kismet2/BlueprintEditorUtils.h" // for FBlueprintEditorUtils::FForceFastBlueprintDuplicationScope
|
|
|
|
DEFINE_LOG_CATEGORY(LogBlueprintCodeGen)
|
|
|
|
/*******************************************************************************
|
|
* BlueprintNativeCodeGenUtilsImpl
|
|
******************************************************************************/
|
|
|
|
namespace BlueprintNativeCodeGenUtilsImpl
|
|
{
|
|
static FString CoreModuleName = TEXT("Core");
|
|
static FString EngineModuleName = TEXT("Engine");
|
|
static FString EngineHeaderFile = TEXT("Engine.h");
|
|
|
|
/**
|
|
* Deletes the files/directories in the supplied array.
|
|
*
|
|
* @param TargetPaths The set of directory and file paths that you want deleted.
|
|
* @return True if all the files/directories were successfully deleted, other wise false.
|
|
*/
|
|
static bool WipeTargetPaths(const FBlueprintNativeCodeGenPaths& TargetPaths);
|
|
|
|
/**
|
|
* Creates and fills out a new .uplugin file for the converted assets.
|
|
*
|
|
* @param PluginName The name of the plugin you're generating.
|
|
* @param TargetPaths Defines the file path/name for the plugin file.
|
|
* @return True if the file was successfully saved, otherwise false.
|
|
*/
|
|
static bool GeneratePluginDescFile(const FString& PluginName, const FBlueprintNativeCodeGenPaths& TargetPaths);
|
|
|
|
/**
|
|
* Creates a module implementation and header file for the converted assets'
|
|
* module (provides a IMPLEMENT_MODULE() declaration, which is required for
|
|
* the module to function).
|
|
*
|
|
* @param TargetPaths Defines the file path/name for the target files.
|
|
* @return True if the files were successfully generated, otherwise false.
|
|
*/
|
|
static bool GenerateModuleSourceFiles(const FBlueprintNativeCodeGenPaths& TargetPaths);
|
|
|
|
/**
|
|
* Creates and fills out a new .Build.cs file for the plugin's runtime module.
|
|
*
|
|
* @param Manifest Defines where the module file should be saved, what it should be named, etc..
|
|
* @return True if the file was successfully saved, otherwise false.
|
|
*/
|
|
static bool GenerateModuleBuildFile(const FBlueprintNativeCodeGenManifest& Manifest);
|
|
|
|
/**
|
|
* Determines what the expected native class will be for an asset that was
|
|
* or will be converted.
|
|
*
|
|
* @param ConversionRecord Identifies the asset's original type (which is used to infer the replacement type from).
|
|
* @return Either a class, enum, or struct class (depending on the asset's type).
|
|
*/
|
|
static UClass* ResolveReplacementType(const FConvertedAssetRecord& ConversionRecord);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenUtilsImpl::WipeTargetPaths(const FBlueprintNativeCodeGenPaths& TargetPaths)
|
|
{
|
|
IFileManager& FileManager = IFileManager::Get();
|
|
|
|
bool bSuccess = true;
|
|
bSuccess &= FileManager.Delete(*TargetPaths.PluginFilePath());
|
|
bSuccess &= FileManager.DeleteDirectory(*TargetPaths.PluginSourceDir(), /*RequireExists =*/false, /*Tree =*/true);
|
|
bSuccess &= FileManager.Delete(*TargetPaths.ManifestFilePath());
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenUtilsImpl::GeneratePluginDescFile(const FString& PluginName, const FBlueprintNativeCodeGenPaths& TargetPaths)
|
|
{
|
|
FPluginDescriptor PluginDesc;
|
|
PluginDesc.FriendlyName = PluginName;
|
|
PluginDesc.CreatedBy = TEXT("Epic Games, Inc.");
|
|
PluginDesc.CreatedByURL = TEXT("http://epicgames.com");
|
|
PluginDesc.Description = TEXT("A programatically generated plugin which contains source files produced from Blueprint assets. The aim of this is to help performance by eliminating script overhead for the converted assets (using the source files in place of thier coresponding assets).");
|
|
PluginDesc.DocsURL = TEXT("@TODO");
|
|
PluginDesc.SupportURL = TEXT("https://answers.unrealengine.com/");
|
|
PluginDesc.Category = TEXT("Intermediate");
|
|
PluginDesc.bEnabledByDefault = true;
|
|
PluginDesc.bCanContainContent = false;
|
|
PluginDesc.bIsBetaVersion = true; // @TODO: change once we're confident in the feature
|
|
|
|
FModuleDescriptor RuntimeModuleDesc;
|
|
RuntimeModuleDesc.Name = *TargetPaths.RuntimeModuleName();
|
|
RuntimeModuleDesc.Type = EHostType::Runtime;
|
|
// load at startup (during engine init), after game modules have been loaded
|
|
RuntimeModuleDesc.LoadingPhase = ELoadingPhase::Default;
|
|
|
|
PluginDesc.Modules.Add(RuntimeModuleDesc);
|
|
|
|
FText ErrorMessage;
|
|
bool bSuccess = PluginDesc.Save(TargetPaths.PluginFilePath(), ErrorMessage);
|
|
|
|
if (!bSuccess)
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Error, TEXT("Failed to generate the plugin description file: %s"), *ErrorMessage.ToString());
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenUtilsImpl::GenerateModuleSourceFiles(const FBlueprintNativeCodeGenPaths& TargetPaths)
|
|
{
|
|
FText FailureReason;
|
|
|
|
TArray<FString> PchIncludes;
|
|
PchIncludes.Add(EngineHeaderFile);
|
|
|
|
bool bSuccess = GameProjectUtils::GeneratePluginModuleHeaderFile(TargetPaths.RuntimeModuleFile(FBlueprintNativeCodeGenPaths::HFile), PchIncludes, FailureReason);
|
|
|
|
if (bSuccess)
|
|
{
|
|
const FString NoStartupCode = TEXT("");
|
|
bSuccess &= GameProjectUtils::GeneratePluginModuleCPPFile(TargetPaths.RuntimeModuleFile(FBlueprintNativeCodeGenPaths::CppFile),
|
|
TargetPaths.RuntimeModuleName(), NoStartupCode, FailureReason);
|
|
}
|
|
|
|
if (!bSuccess)
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Error, TEXT("Failed to generate module source files: %s"), *FailureReason.ToString());
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static bool BlueprintNativeCodeGenUtilsImpl::GenerateModuleBuildFile(const FBlueprintNativeCodeGenManifest& Manifest)
|
|
{
|
|
FModuleManager& ModuleManager = FModuleManager::Get();
|
|
|
|
TArray<FString> PublicDependencies;
|
|
// for IModuleInterface
|
|
PublicDependencies.Add(CoreModuleName);
|
|
// for Engine.h
|
|
PublicDependencies.Add(EngineModuleName);
|
|
|
|
if (GameProjectUtils::ProjectHasCodeFiles())
|
|
{
|
|
const FString GameModuleName = FApp::GetGameName();
|
|
if (ModuleManager.ModuleExists(*GameModuleName))
|
|
{
|
|
PublicDependencies.Add(GameModuleName);
|
|
}
|
|
}
|
|
|
|
TArray<FString> PrivateDependencies;
|
|
|
|
const TArray<UPackage*>& ModulePackages = Manifest.GetModuleDependencies();
|
|
PrivateDependencies.Reserve(ModulePackages.Num());
|
|
|
|
for (UPackage* ModulePkg : ModulePackages)
|
|
{
|
|
const FString PkgModuleName = FPackageName::GetLongPackageAssetName(ModulePkg->GetName());
|
|
if (ModuleManager.ModuleExists(*PkgModuleName))
|
|
{
|
|
PrivateDependencies.Add(PkgModuleName);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Warning, TEXT("Failed to find module for package: %s"), *PkgModuleName);
|
|
}
|
|
}
|
|
|
|
FBlueprintNativeCodeGenPaths TargetPaths = Manifest.GetTargetPaths();
|
|
|
|
FText ErrorMessage;
|
|
bool bSuccess = GameProjectUtils::GenerateGameModuleBuildFile(TargetPaths.RuntimeBuildFile(), TargetPaths.RuntimeModuleName(),
|
|
PublicDependencies, PrivateDependencies, ErrorMessage);
|
|
|
|
if (!bSuccess)
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Error, TEXT("Failed to generate module build file: %s"), *ErrorMessage.ToString());
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static UClass* BlueprintNativeCodeGenUtilsImpl::ResolveReplacementType(const FConvertedAssetRecord& ConversionRecord)
|
|
{
|
|
const UClass* AssetType = ConversionRecord.AssetType;
|
|
check(AssetType != nullptr);
|
|
|
|
if (AssetType->IsChildOf<UUserDefinedEnum>())
|
|
{
|
|
return UEnum::StaticClass();
|
|
}
|
|
else if (AssetType->IsChildOf<UUserDefinedStruct>())
|
|
{
|
|
return UScriptStruct::StaticClass();
|
|
}
|
|
else if (AssetType->IsChildOf<UBlueprint>())
|
|
{
|
|
return UDynamicClass::StaticClass();
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Error, TEXT("Unsupported asset type (%s); cannot determine replacement type."), *AssetType->GetName());
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FBlueprintNativeCodeGenUtils
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FBlueprintNativeCodeGenUtils::FinalizePlugin(const FBlueprintNativeCodeGenManifest& Manifest, const FNativeCodeGenCommandlineParams& CommandParams)
|
|
{
|
|
bool bSuccess = true;
|
|
bSuccess = bSuccess && BlueprintNativeCodeGenUtilsImpl::GenerateModuleBuildFile(Manifest);
|
|
bSuccess = bSuccess && BlueprintNativeCodeGenUtilsImpl::GenerateModuleSourceFiles(Manifest.GetTargetPaths());
|
|
bSuccess = bSuccess && BlueprintNativeCodeGenUtilsImpl::GeneratePluginDescFile(CommandParams.PluginName, Manifest.GetTargetPaths());
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void FBlueprintNativeCodeGenUtils::GenerateCppCode(UObject* Obj, TSharedPtr<FString> OutHeaderSource, TSharedPtr<FString> OutCppSource)
|
|
{
|
|
auto UDEnum = Cast<UUserDefinedEnum>(Obj);
|
|
auto UDStruct = Cast<UUserDefinedStruct>(Obj);
|
|
auto BPGC = Cast<UClass>(Obj);
|
|
auto InBlueprintObj = BPGC ? Cast<UBlueprint>(BPGC->ClassGeneratedBy) : Cast<UBlueprint>(Obj);
|
|
|
|
OutHeaderSource->Empty();
|
|
OutCppSource->Empty();
|
|
|
|
if (InBlueprintObj)
|
|
{
|
|
if (EBlueprintStatus::BS_Error == InBlueprintObj->Status)
|
|
{
|
|
UE_LOG(LogBlueprintCodeGen, Error, TEXT("Cannot convert \"%s\". It has errors."), *InBlueprintObj->GetPathName());
|
|
return;
|
|
}
|
|
|
|
check(InBlueprintObj->GetOutermost() != GetTransientPackage());
|
|
if (!ensureMsgf(InBlueprintObj->GeneratedClass, TEXT("Invalid generated class for %s"), *InBlueprintObj->GetName()))
|
|
{
|
|
return;
|
|
}
|
|
check(OutHeaderSource.IsValid());
|
|
check(OutCppSource.IsValid());
|
|
|
|
FDisableGatheringDataOnScope DisableFib;
|
|
|
|
const FString TempPackageName = FString::Printf(TEXT("/Temp/__TEMP_BP__/%s"), *InBlueprintObj->GetName());
|
|
UPackage* TempPackage = CreatePackage(nullptr, *TempPackageName);
|
|
check(TempPackage);
|
|
ON_SCOPE_EXIT
|
|
{
|
|
TempPackage->RemoveFromRoot();
|
|
TempPackage->MarkPendingKill();
|
|
};
|
|
|
|
UBlueprint* DuplicateBP = nullptr;
|
|
{
|
|
FBlueprintDuplicationScopeFlags BPDuplicationFlags(
|
|
FBlueprintDuplicationScopeFlags::NoExtraCompilation | FBlueprintDuplicationScopeFlags::TheSameTimelineGuid);
|
|
DuplicateBP = DuplicateObject<UBlueprint>(InBlueprintObj, TempPackage, *InBlueprintObj->GetName());
|
|
}
|
|
ensure((nullptr != DuplicateBP->GeneratedClass) && (InBlueprintObj->GeneratedClass != DuplicateBP->GeneratedClass));
|
|
ON_SCOPE_EXIT
|
|
{
|
|
DuplicateBP->RemoveFromRoot();
|
|
DuplicateBP->MarkPendingKill();
|
|
};
|
|
|
|
IBlueprintCompilerCppBackendModule& CodeGenBackend = (IBlueprintCompilerCppBackendModule&)IBlueprintCompilerCppBackendModule::Get();
|
|
CodeGenBackend.GetOriginalClassMap().Add(*DuplicateBP->GeneratedClass, *InBlueprintObj->GeneratedClass);
|
|
|
|
{
|
|
TSharedPtr<FBlueprintCompileReinstancer> Reinstancer = FBlueprintCompileReinstancer::Create(DuplicateBP->GeneratedClass);
|
|
IKismetCompilerInterface& Compiler = FModuleManager::LoadModuleChecked<IKismetCompilerInterface>(KISMET_COMPILER_MODULENAME);
|
|
TGuardValue<bool> GuardTemplateNameFlag(GCompilingBlueprint, true);
|
|
FCompilerResultsLog Results;
|
|
|
|
FKismetCompilerOptions CompileOptions;
|
|
CompileOptions.CompileType = EKismetCompileType::Cpp;
|
|
CompileOptions.OutCppSourceCode = OutCppSource;
|
|
CompileOptions.OutHeaderSourceCode = OutHeaderSource;
|
|
|
|
Compiler.CompileBlueprint(DuplicateBP, CompileOptions, Results);
|
|
|
|
Compiler.RemoveBlueprintGeneratedClasses(DuplicateBP);
|
|
}
|
|
|
|
if (EBlueprintType::BPTYPE_Interface == DuplicateBP->BlueprintType && OutCppSource.IsValid())
|
|
{
|
|
OutCppSource->Empty(); // ugly temp hack
|
|
}
|
|
}
|
|
else if ((UDEnum || UDStruct) && OutHeaderSource.IsValid())
|
|
{
|
|
IKismetCompilerInterface& Compiler = FModuleManager::LoadModuleChecked<IKismetCompilerInterface>(KISMET_COMPILER_MODULENAME);
|
|
if (UDEnum)
|
|
{
|
|
*OutHeaderSource = Compiler.GenerateCppCodeForEnum(UDEnum);
|
|
}
|
|
else if (UDStruct)
|
|
{
|
|
*OutHeaderSource = Compiler.GenerateCppCodeForStruct(UDStruct);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ensure(false);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FScopedFeedbackContext
|
|
******************************************************************************/
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenUtils::FScopedFeedbackContext::FScopedFeedbackContext()
|
|
: OldContext(GWarn)
|
|
, ErrorCount(0)
|
|
, WarningCount(0)
|
|
{
|
|
TreatWarningsAsErrors = GWarn->TreatWarningsAsErrors;
|
|
GWarn = this;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
FBlueprintNativeCodeGenUtils::FScopedFeedbackContext::~FScopedFeedbackContext()
|
|
{
|
|
GWarn = OldContext;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool FBlueprintNativeCodeGenUtils::FScopedFeedbackContext::HasErrors()
|
|
{
|
|
return (ErrorCount > 0) || (TreatWarningsAsErrors && (WarningCount > 0));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void FBlueprintNativeCodeGenUtils::FScopedFeedbackContext::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const class FName& Category)
|
|
{
|
|
switch (Verbosity)
|
|
{
|
|
case ELogVerbosity::Warning:
|
|
{
|
|
++WarningCount;
|
|
}
|
|
break;
|
|
|
|
case ELogVerbosity::Error:
|
|
case ELogVerbosity::Fatal:
|
|
{
|
|
++ErrorCount;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
OldContext->Serialize(V, Verbosity, Category);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void FBlueprintNativeCodeGenUtils::FScopedFeedbackContext::Flush()
|
|
{
|
|
WarningCount = ErrorCount = 0;
|
|
OldContext->Flush();
|
|
}
|