//------------------------------------------------------------------------------ bool BlueprintNodeTemplateCacheImpl::IsTemplateOuter(UEdGraph* ParentGraph) { if (ParentGraph->HasAnyFlags(RF_Transactional)) { UPackage* GraphPackage = ParentGraph->GetOutermost(); UMetaData* PackageMetadata = GraphPackage->GetMetaData(); return PackageMetadata->HasValue(ParentGraph, TemplateGraphMetaTag); } return false; }
// Rename a class and it's CDO into the transient package, and clear RF_Public on both of them void FKismetCompilerUtilities::ConsignToOblivion(UClass* OldClass, bool bForceNoResetLoaders) { if (OldClass != NULL) { // Use the Kismet class reinstancer to ensure that the CDO and any existing instances of this class are cleaned up! FBlueprintCompileReinstancer CTOResinstancer(OldClass); UPackage* OwnerOutermost = OldClass->GetOutermost(); if( OldClass->ClassDefaultObject ) { // rename to a temp name, move into transient package OldClass->ClassDefaultObject->ClearFlags(RF_Public); OldClass->ClassDefaultObject->SetFlags(RF_Transient); OldClass->ClassDefaultObject->RemoveFromRoot(); // make sure no longer in root set } OldClass->SetMetaData(FBlueprintMetadata::MD_IsBlueprintBase, TEXT("false")); OldClass->ClearFlags(RF_Public); OldClass->SetFlags(RF_Transient); OldClass->ClassFlags |= CLASS_Deprecated|CLASS_NewerVersionExists; OldClass->RemoveFromRoot(); // make sure no longer in root set // Invalidate the export for all old properties, to make sure they don't get partially reloaded and corrupt the class for( TFieldIterator<UProperty> It(OldClass,EFieldIteratorFlags::ExcludeSuper); It; ++It ) { UProperty* Current = *It; InvalidatePropertyExport(Current); } for( TFieldIterator<UFunction> ItFunc(OldClass,EFieldIteratorFlags::ExcludeSuper); ItFunc; ++ItFunc ) { UFunction* CurrentFunc = *ItFunc; ULinkerLoad::InvalidateExport(CurrentFunc); for( TFieldIterator<UProperty> It(CurrentFunc,EFieldIteratorFlags::ExcludeSuper); It; ++It ) { UProperty* Current = *It; InvalidatePropertyExport(Current); } } const FString BaseName = FString::Printf(TEXT("DEADCLASS_%s_C_%d"), *OldClass->ClassGeneratedBy->GetName(), ConsignToOblivionCounter++); OldClass->Rename(*BaseName, GetTransientPackage(), (REN_DontCreateRedirectors|REN_NonTransactional|(bForceNoResetLoaders ? REN_ForceNoResetLoaders : 0))); // Make sure MetaData doesn't have any entries to the class we just renamed out of package OwnerOutermost->GetMetaData()->RemoveMetaDataOutsidePackage(); } }
// Compiles a blueprint. void FKismet2CompilerModule::CompileBlueprint(class UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions, FCompilerResultsLog& Results, FBlueprintCompileReinstancer* ParentReinstancer, TArray<UObject*>* ObjLoaded) { SCOPE_SECONDS_COUNTER(GBlueprintCompileTime); BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileTime); Results.SetSourceName(Blueprint->GetName()); const bool bIsBrandNewBP = (Blueprint->SkeletonGeneratedClass == NULL) && (Blueprint->GeneratedClass == NULL) && (Blueprint->ParentClass != NULL) && !CompileOptions.bIsDuplicationInstigated; for ( IBlueprintCompiler* Compiler : Compilers ) { Compiler->PreCompile(Blueprint); } if (CompileOptions.CompileType != EKismetCompileType::Cpp) { BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileSkeletonClass); FBlueprintCompileReinstancer SkeletonReinstancer(Blueprint->SkeletonGeneratedClass); FCompilerResultsLog SkeletonResults; SkeletonResults.bSilentMode = true; FKismetCompilerOptions SkeletonCompileOptions; SkeletonCompileOptions.CompileType = EKismetCompileType::SkeletonOnly; CompileBlueprintInner(Blueprint, SkeletonCompileOptions, SkeletonResults, ObjLoaded); } // If this was a full compile, take appropriate actions depending on the success of failure of the compile if( CompileOptions.IsGeneratedClassCompileType() ) { BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileGeneratedClass); // Perform the full compile CompileBlueprintInner(Blueprint, CompileOptions, Results, ObjLoaded); if (Results.NumErrors == 0) { // Blueprint is error free. Go ahead and fix up debug info Blueprint->Status = (0 == Results.NumWarnings) ? BS_UpToDate : BS_UpToDateWithWarnings; Blueprint->BlueprintSystemVersion = UBlueprint::GetCurrentBlueprintSystemVersion(); // Reapply breakpoints to the bytecode of the new class for (int32 Index = 0; Index < Blueprint->Breakpoints.Num(); ++Index) { UBreakpoint* Breakpoint = Blueprint->Breakpoints[Index]; FKismetDebugUtilities::ReapplyBreakpoint(Breakpoint); } } else { // Should never get errors from a brand new blueprint! ensure(!bIsBrandNewBP || (Results.NumErrors == 0)); // There were errors. Compile the generated class to have function stubs Blueprint->Status = BS_Error; static const FBoolConfigValueHelper ReinstanceOnlyWhenNecessary(TEXT("Kismet"), TEXT("bReinstanceOnlyWhenNecessary"), GEngineIni); // Reinstance objects here, so we can preserve their memory layouts to reinstance them again if( ParentReinstancer != NULL ) { ParentReinstancer->UpdateBytecodeReferences(); if(!Blueprint->bIsRegeneratingOnLoad) { ParentReinstancer->ReinstanceObjects(!ReinstanceOnlyWhenNecessary); } } FBlueprintCompileReinstancer StubReinstancer(Blueprint->GeneratedClass); // Toss the half-baked class and generate a stubbed out skeleton class that can be used FCompilerResultsLog StubResults; StubResults.bSilentMode = true; FKismetCompilerOptions StubCompileOptions(CompileOptions); StubCompileOptions.CompileType = EKismetCompileType::StubAfterFailure; CompileBlueprintInner(Blueprint, StubCompileOptions, StubResults, ObjLoaded); StubReinstancer.UpdateBytecodeReferences(); if( !Blueprint->bIsRegeneratingOnLoad ) { StubReinstancer.ReinstanceObjects(!ReinstanceOnlyWhenNecessary); } } } for ( IBlueprintCompiler* Compiler : Compilers ) { Compiler->PostCompile(Blueprint); } UPackage* Package = Blueprint->GetOutermost(); if( Package ) { UMetaData* MetaData = Package->GetMetaData(); MetaData->RemoveMetaDataOutsidePackage(); } }
//------------------------------------------------------------------------------ static void BlueprintNodeTemplateCacheImpl::MarkGraphForTemplateUse(UEdGraph* NewGraph) { UPackage* TemplatePackage = NewGraph->GetOutermost(); UMetaData* PackageMetadata = TemplatePackage->GetMetaData(); PackageMetadata->SetValue(NewGraph, TemplateGraphMetaTag, TEXT("true")); }