void FAssetFixUpRedirectors::DeleteRedirectors(TArray<FRedirectorRefs>& RedirectorsToFix) const { TArray<UObject*> ObjectsToDelete; for ( auto RedirectorIt = RedirectorsToFix.CreateIterator(); RedirectorIt; ++RedirectorIt ) { FRedirectorRefs& RedirectorRefs = *RedirectorIt; if ( RedirectorRefs.bRedirectorValidForFixup ) { // Add all redirectors found in this package to the redirectors to delete list. // All redirectors in this package should be fixed up. UPackage* RedirectorPackage = RedirectorRefs.Redirector->GetOutermost(); TArray<UObject*> AssetsInRedirectorPackage; GetObjectsWithOuter(RedirectorPackage, AssetsInRedirectorPackage, /*bIncludeNestedObjects=*/false); UMetaData* PackageMetaData = NULL; bool bContainsAtLeastOneOtherAsset = false; for ( auto ObjIt = AssetsInRedirectorPackage.CreateConstIterator(); ObjIt; ++ObjIt ) { if ( UObjectRedirector* Redirector = Cast<UObjectRedirector>(*ObjIt) ) { Redirector->RemoveFromRoot(); ObjectsToDelete.Add(Redirector); } else if ( UMetaData* MetaData = Cast<UMetaData>(*ObjIt) ) { PackageMetaData = MetaData; } else { bContainsAtLeastOneOtherAsset = true; } } if ( !bContainsAtLeastOneOtherAsset ) { RedirectorPackage->RemoveFromRoot(); ULinkerLoad* Linker = ULinkerLoad::FindExistingLinkerForPackage(RedirectorPackage); if ( Linker ) { Linker->RemoveFromRoot(); } // @todo we shouldnt be worrying about metadata objects here, ObjectTools::CleanUpAfterSuccessfulDelete should if ( PackageMetaData ) { PackageMetaData->RemoveFromRoot(); ObjectsToDelete.Add(PackageMetaData); } } // This redirector will be deleted, NULL the reference here RedirectorRefs.Redirector = NULL; } } if ( ObjectsToDelete.Num() > 0 ) { ObjectTools::DeleteObjects(ObjectsToDelete); } }
void FAssetDeleteModel::PrepareToDelete(UObject* InObject) { if ( InObject->IsA<UObjectRedirector>() ) { // Add all redirectors found in this package to the redirectors to delete list. // All redirectors in this package should be fixed up. UPackage* RedirectorPackage = InObject->GetOutermost(); TArray<UObject*> AssetsInRedirectorPackage; GetObjectsWithOuter(RedirectorPackage, AssetsInRedirectorPackage, /*bIncludeNestedObjects=*/false); UMetaData* PackageMetaData = NULL; bool bContainsAtLeastOneOtherAsset = false; for ( auto ObjIt = AssetsInRedirectorPackage.CreateConstIterator(); ObjIt; ++ObjIt ) { if ( UObjectRedirector* Redirector = Cast<UObjectRedirector>(*ObjIt) ) { Redirector->RemoveFromRoot(); } else if ( UMetaData* MetaData = Cast<UMetaData>(*ObjIt) ) { PackageMetaData = MetaData; } else { bContainsAtLeastOneOtherAsset = true; } } if ( !bContainsAtLeastOneOtherAsset ) { RedirectorPackage->RemoveFromRoot(); ULinkerLoad* Linker = ULinkerLoad::FindExistingLinkerForPackage(RedirectorPackage); if ( Linker ) { Linker->RemoveFromRoot(); } // @todo we shouldnt be worrying about metadata objects here, ObjectTools::CleanUpAfterSuccessfulDelete should if ( PackageMetaData ) { PackageMetaData->RemoveFromRoot(); PendingDeletes.AddUnique(MakeShareable(new FPendingDelete(PackageMetaData))); } } } }
//------------------------------------------------------------------------------ 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())
void FAssetFixUpRedirectors::DeleteRedirectors(TArray<FRedirectorRefs>& RedirectorsToFix, const TArray<UPackage*>& FailedToSave) const { TArray<UObject*> ObjectsToDelete; for ( auto RedirectorIt = RedirectorsToFix.CreateIterator(); RedirectorIt; ++RedirectorIt ) { FRedirectorRefs& RedirectorRefs = *RedirectorIt; if ( RedirectorRefs.bRedirectorValidForFixup ) { bool bAllReferencersFixedUp = true; for (const auto& ReferencingPackageName : RedirectorRefs.ReferencingPackageNames) { if (FailedToSave.ContainsByPredicate([&](UPackage* Package) { return Package->GetFName() == ReferencingPackageName; })) { bAllReferencersFixedUp = false; break; } } if (!bAllReferencersFixedUp) { continue; } // Add all redirectors found in this package to the redirectors to delete list. // All redirectors in this package should be fixed up. UPackage* RedirectorPackage = RedirectorRefs.Redirector->GetOutermost(); TArray<UObject*> AssetsInRedirectorPackage; GetObjectsWithOuter(RedirectorPackage, AssetsInRedirectorPackage, /*bIncludeNestedObjects=*/false); UMetaData* PackageMetaData = NULL; bool bContainsAtLeastOneOtherAsset = false; for ( auto ObjIt = AssetsInRedirectorPackage.CreateConstIterator(); ObjIt; ++ObjIt ) { if ( UObjectRedirector* Redirector = Cast<UObjectRedirector>(*ObjIt) ) { Redirector->RemoveFromRoot(); ObjectsToDelete.Add(Redirector); } else if ( UMetaData* MetaData = Cast<UMetaData>(*ObjIt) ) { PackageMetaData = MetaData; } else { bContainsAtLeastOneOtherAsset = true; } } if ( !bContainsAtLeastOneOtherAsset ) { RedirectorPackage->RemoveFromRoot(); // @todo we shouldnt be worrying about metadata objects here, ObjectTools::CleanUpAfterSuccessfulDelete should if ( PackageMetaData ) { PackageMetaData->RemoveFromRoot(); ObjectsToDelete.Add(PackageMetaData); } } // This redirector will be deleted, NULL the reference here RedirectorRefs.Redirector = NULL; } } if ( ObjectsToDelete.Num() > 0 ) { ObjectTools::DeleteObjects(ObjectsToDelete, false); } }