void FBlueprintNativeCodeGenModule::InitializeForRerunDebugOnly(const TArray< TPair< FString, FString > >& CodegenTargets) { ReadConfig(); IBlueprintNativeCodeGenCore::Register(this); FillTargetedForReplacementQuery(); FillIsFunctionUsedInADelegate(); for (const auto& Platform : CodegenTargets) { // load the old manifest: const TCHAR* TargetDirectory = *Platform.Value; FString OutputPath = FPaths::Combine(TargetDirectory, NativizationCookControllerImpl::DefaultPluginName, *FBlueprintNativeCodeGenPaths::GetDefaultManifestPath()); Manifests.Add(FString(*Platform.Key), TUniquePtr<FBlueprintNativeCodeGenManifest>(new FBlueprintNativeCodeGenManifest(FPaths::ConvertRelativePathToFull(OutputPath)))); //FBlueprintNativeCodeGenManifest OldManifest(FPaths::ConvertRelativePathToFull(OutputPath)); // reconvert every assets listed in the manifest: for (const auto& ConversionTarget : GetManifest(*Platform.Key).GetConversionRecord()) { // load the package: UPackage* Package = LoadPackage(nullptr, *ConversionTarget.Value.TargetObjPath, LOAD_None); if (!Package) { UE_LOG(LogBlueprintCodeGen, Error, TEXT("Unable to load the package: %s"), *ConversionTarget.Value.TargetObjPath); continue; } // reconvert it Convert(Package, ESavePackageResult::ReplaceCompletely, *Platform.Key); } // reconvert every unconverted dependency listed in the manifest: for (const auto& ConversionTarget : GetManifest(*Platform.Key).GetUnconvertedDependencies()) { // load the package: UPackage* Package = LoadPackage(nullptr, *ConversionTarget.Key.GetPlainNameString(), LOAD_None); UStruct* Struct = nullptr; UEnum* Enum = nullptr; GetFieldFormPackage(Package, Struct, Enum); UBlueprint* BP = Cast<UBlueprint>(CastChecked<UClass>(Struct)->ClassGeneratedBy); if (ensure(BP)) { CollectBoundFunctions(BP); GenerateSingleStub(BP, *Platform.Key); } } for (TAssetPtr<UBlueprint>& BPPtr : ToGenerate) { UBlueprint* BP = BPPtr.LoadSynchronous(); if (ensure(BP)) { GenerateSingleAsset(BP->GeneratedClass, *Platform.Key); } } } }
bool FCreatePackageLatentCommand::Update() { FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools"); FString PackageName; FString AssetName; AssetToolsModule.Get().CreateUniqueAssetName(CommandChain.Parameter, TEXT("New"), PackageName, AssetName); FString OriginalPackageName = SourceControlHelpers::PackageFilename(CommandChain.Parameter); FString NewPackageName = SourceControlHelpers::PackageFilename(PackageName); if(FPlatformFileManager::Get().GetPlatformFile().CopyFile(*NewPackageName, *OriginalPackageName)) { UPackage* Package = LoadPackage(NULL, *NewPackageName, LOAD_None); if(Package != NULL) { CommandChain.LatentCommandDelegate.ExecuteIfBound(PackageName); } else { UE_LOG(LogSourceControl, Error, TEXT("Could not load temporary package '%s'"), *PackageName); } } else { UE_LOG(LogSourceControl, Error, TEXT("Could not create temporary package to add '%s'"), *PackageName); } return true; }
UClass* FClassData::GetClass() { UClass* RetClass = Class.Get(); if (RetClass == NULL && GeneratedClassPackage.Len()) { GWarn->BeginSlowTask(LOCTEXT("LoadPackage", "Loading Package..."), true); UPackage* Package = LoadPackage(NULL, *GeneratedClassPackage, LOAD_NoRedirects); if (Package) { Package->FullyLoad(); UObject* Object = FindObject<UObject>(Package, *AssetName); GWarn->EndSlowTask(); UBlueprint* BlueprintOb = Cast<UBlueprint>(Object); RetClass = BlueprintOb ? *BlueprintOb->GeneratedClass : Object->GetClass(); Class = RetClass; } else { GWarn->EndSlowTask(); FMessageLog EditorErrors("EditorErrors"); EditorErrors.Error(LOCTEXT("PackageLoadFail", "Package Load Failed")); EditorErrors.Info(FText::FromString(GeneratedClassPackage)); EditorErrors.Notify(LOCTEXT("PackageLoadFail", "Package Load Failed")); } } return RetClass; }
UPKReader::UPKReader(const char* filename) { if (!LoadPackage(filename)) { LogError("Object was not initialized properly due to read errors!"); } }
bool FEditTextureLatentCommand::Update() { // make a minor edit to the texture in the package we are passed UPackage* Package = LoadPackage(NULL, *PackageName, LOAD_None); if(Package != NULL) { UTexture2D* Texture = FindObject<UTexture2D>(Package, TEXT("SourceControlTest")); check(Texture); Texture->AdjustBrightness = FMath::FRand(); Package->SetDirtyFlag(true); if(!UPackage::SavePackage(Package, NULL, RF_Standalone, *FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension()))) { UE_LOG(LogSourceControl, Error, TEXT("Could not save package: '%s'"), *PackageName); } TArray<UPackage*> Packages; Packages.Add(Package); PackageTools::UnloadPackages(Packages); } else { UE_LOG(LogSourceControl, Error, TEXT("Could not find package for edit: '%s'"), *PackageName); } return true; }
void FStartupPackages::LoadPackageList(const TArray<FString>& PackageNames) { // Iterate over all native script packages and fully load them. for( int32 PackageIndex=0; PackageIndex<PackageNames.Num(); PackageIndex++ ) { UObject* Package = LoadPackage(NULL, *PackageNames[PackageIndex], LOAD_None); } }
const BOOLEAN CSprite::Load(const PCHAR name) { Clear(); const HPACKAGE package=LoadPackage(name); if (package.p==NULL)return FALSE; DWORD size; // Erst Anzahl in Package testen LPVOID data=LoadNextPackageData(&package,NULL,&size); anzahl=0; while (data) { anzahl++; data=LoadNextPackageData(&package,data,&size); } if (anzahl==0) { FreePackage(&package); return FALSE; } // Speicher reservieren lpImages=new LPDIRECTDRAWSURFACE7[anzahl]; // Dann Bilder laden data=LoadNextPackageData(&package,NULL,&size); anzahl=0; while (data) { HBITMAP bitmap=LoadPictureFromMemory(data,size); if (bitmap==0) { FreePackage(&package); return FALSE; } lpImages[anzahl]=CreateTextureFromBitmap(game->lpDevice,game->lpDD,NULL,bitmap,3,TRUE,TRUE,FALSE); if (lpImages[anzahl]!=NULL) MakeTransparent(lpImages[anzahl],FALSE); DeleteObject(bitmap); anzahl++; data=LoadNextPackageData(&package,data,&size); } FreePackage(&package); #ifdef _DEBUG CHAR c[200]; sprintf(&c[0],"Sprite geladen: %s",name); DebugOut(&c[0]); #endif return TRUE; }
void FAssetFixUpRedirectors::LoadReferencingPackages(TArray<FRedirectorRefs>& RedirectorsToFix, TArray<UPackage*>& OutReferencingPackagesToSave) const { FScopedSlowTask SlowTask( RedirectorsToFix.Num(), LOCTEXT( "LoadingReferencingPackages", "Loading Referencing Packages..." ) ); SlowTask.MakeDialog(); ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); // Load all packages that reference each redirector, if possible for ( auto RedirectorRefsIt = RedirectorsToFix.CreateIterator(); RedirectorRefsIt; ++RedirectorRefsIt ) { SlowTask.EnterProgressFrame(1); FRedirectorRefs& RedirectorRefs = *RedirectorRefsIt; if ( ISourceControlModule::Get().IsEnabled() ) { FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(RedirectorRefs.Redirector->GetOutermost(), EStateCacheUsage::Use); const bool bValidSCCState = !SourceControlState.IsValid() || SourceControlState->IsAdded() || SourceControlState->IsCheckedOut() || SourceControlState->CanCheckout() || !SourceControlState->IsSourceControlled() || SourceControlState->IsIgnored(); if ( !bValidSCCState ) { RedirectorRefs.bRedirectorValidForFixup = false; RedirectorRefs.FailureReason = LOCTEXT("RedirectorFixupFailed_BadSCC", "Redirector could not be checked out or marked for delete"); } } // Load all referencers for ( auto PackageNameIt = RedirectorRefs.ReferencingPackageNames.CreateConstIterator(); PackageNameIt; ++PackageNameIt ) { const FString PackageName = (*PackageNameIt).ToString(); // Find the package in memory. If it is not in memory, try to load it UPackage* Package = FindPackage(NULL, *PackageName); if ( !Package ) { Package = LoadPackage(NULL, *PackageName, LOAD_None); } if ( Package ) { if ( Package->PackageFlags & PKG_CompiledIn ) { // This is a script reference RedirectorRefs.bRedirectorValidForFixup = false; RedirectorRefs.FailureReason = FText::Format(LOCTEXT("RedirectorFixupFailed_CodeReference", "Redirector is referenced by code. Package: {0}"), FText::FromString(PackageName)); } else { // If we found a valid package, mark it for save OutReferencingPackagesToSave.AddUnique(Package); } } } } }
void FAssetEditorManager::OpenEditorForAsset(const FString& AssetPathName) { // An asset needs loading UPackage* Package = LoadPackage(NULL, *AssetPathName, LOAD_NoRedirects); if (Package) { Package->FullyLoad(); FString AssetName = FPaths::GetBaseFilename(AssetPathName); UObject* Object = FindObject<UObject>(Package, *AssetName); if (Object != NULL) { OpenEditorForAsset(Object); } } }
/** * Fully loads this package. Safe to call multiple times and won't clobber already loaded assets. */ void UPackage::FullyLoad() { // Make sure we're a topmost package. check(GetOuter()==NULL); // Only perform work if we're not already fully loaded. if( !IsFullyLoaded() ) { // Mark package so exports are found in memory first instead of being clobbered. bool bSavedState = ShouldFindExportsInMemoryFirst(); FindExportsInMemoryFirst( true ); // Re-load this package. LoadPackage( NULL, *GetName(), LOAD_None ); // Restore original state. FindExportsInMemoryFirst( bSavedState ); } }
bool UDiffAssetsCommandlet::LoadFile(const FString& Filename, TArray<UObject *>& LoadedObjects) { UPackage* Package = Cast<UPackage>(LoadPackage( NULL, *Filename, LOAD_None )); if (!Package) { UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Could not load %s"), *Filename); return false; } for (TObjectIterator<UObject> It; It; ++It) { if (It->GetOuter() == Package) { LoadedObjects.Add(*It); } } if (!LoadedObjects.Num()) { UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Loaded %s, but it didn't contain any objects."), *Filename); return false; } LoadedObjects.Sort(); return true; }
int32 UGatherTextFromAssetsCommandlet::Main(const FString& Params) { // Parse command line. TArray<FString> Tokens; TArray<FString> Switches; TMap<FString, FString> ParamVals; UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals); //Set config file const FString* ParamVal = ParamVals.Find(FString(TEXT("Config"))); FString GatherTextConfigPath; if ( ParamVal ) { GatherTextConfigPath = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config specified.")); return -1; } //Set config section ParamVal = ParamVals.Find(FString(TEXT("Section"))); FString SectionName; if ( ParamVal ) { SectionName = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config section specified.")); return -1; } //Modules to Preload TArray<FString> ModulesToPreload; GetStringArrayFromConfig(*SectionName, TEXT("ModulesToPreload"), ModulesToPreload, GatherTextConfigPath); for (const FString& ModuleName : ModulesToPreload) { FModuleManager::Get().LoadModule(*ModuleName); } // IncludePathFilters TArray<FString> IncludePathFilters; GetPathArrayFromConfig(*SectionName, TEXT("IncludePathFilters"), IncludePathFilters, GatherTextConfigPath); // IncludePaths (DEPRECATED) { TArray<FString> IncludePaths; GetPathArrayFromConfig(*SectionName, TEXT("IncludePaths"), IncludePaths, GatherTextConfigPath); if (IncludePaths.Num()) { IncludePathFilters.Append(IncludePaths); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("IncludePaths detected in section %s. IncludePaths is deprecated, please use IncludePathFilters."), *SectionName); } } if (IncludePathFilters.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No include path filters in section %s."), *SectionName); return -1; } // ExcludePathFilters TArray<FString> ExcludePathFilters; GetPathArrayFromConfig(*SectionName, TEXT("ExcludePathFilters"), ExcludePathFilters, GatherTextConfigPath); // ExcludePaths (DEPRECATED) { TArray<FString> ExcludePaths; GetPathArrayFromConfig(*SectionName, TEXT("ExcludePaths"), ExcludePaths, GatherTextConfigPath); if (ExcludePaths.Num()) { ExcludePathFilters.Append(ExcludePaths); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("ExcludePaths detected in section %s. ExcludePaths is deprecated, please use ExcludePathFilters."), *SectionName); } } // PackageNameFilters TArray<FString> PackageFileNameFilters; GetStringArrayFromConfig(*SectionName, TEXT("PackageFileNameFilters"), PackageFileNameFilters, GatherTextConfigPath); // PackageExtensions (DEPRECATED) { TArray<FString> PackageExtensions; GetStringArrayFromConfig(*SectionName, TEXT("PackageExtensions"), PackageExtensions, GatherTextConfigPath); if (PackageExtensions.Num()) { PackageFileNameFilters.Append(PackageExtensions); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("PackageExtensions detected in section %s. PackageExtensions is deprecated, please use PackageFileNameFilters."), *SectionName); } } if (PackageFileNameFilters.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No package file name filters in section %s."), *SectionName); return -1; } //asset class exclude TArray<FString> ExcludeClasses; GetStringArrayFromConfig(*SectionName, TEXT("ExcludeClasses"), ExcludeClasses, GatherTextConfigPath); FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); AssetRegistryModule.Get().SearchAllAssets( true ); FARFilter Filter; for(const auto& ExcludeClass : ExcludeClasses) { UClass* FilterClass = FindObject<UClass>(ANY_PACKAGE, *ExcludeClass); if(FilterClass) { Filter.ClassNames.Add( FilterClass->GetFName() ); } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Invalid exclude class %s"), *ExcludeClass); } } TArray<FAssetData> AssetDataArray; AssetRegistryModule.Get().GetAssets(Filter, AssetDataArray); FString UAssetPackageExtension = FPackageName::GetAssetPackageExtension(); TSet< FString > LongPackageNamesToExclude; for (int Index = 0; Index < AssetDataArray.Num(); Index++) { LongPackageNamesToExclude.Add( FPackageName::LongPackageNameToFilename( AssetDataArray[Index].PackageName.ToString(), UAssetPackageExtension ) ); } //Get whether we should fix broken properties that we find. if (!GetBoolFromConfig(*SectionName, TEXT("bFixBroken"), bFixBroken, GatherTextConfigPath)) { bFixBroken = false; } // Get whether we should gather editor-only data. Typically only useful for the localization of UE4 itself. if (!GetBoolFromConfig(*SectionName, TEXT("ShouldGatherFromEditorOnlyData"), ShouldGatherFromEditorOnlyData, GatherTextConfigPath)) { ShouldGatherFromEditorOnlyData = false; } // Add any manifest dependencies if they were provided TArray<FString> ManifestDependenciesList; GetPathArrayFromConfig(*SectionName, TEXT("ManifestDependencies"), ManifestDependenciesList, GatherTextConfigPath); if( !ManifestInfo->AddManifestDependencies( ManifestDependenciesList ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("The GatherTextFromAssets commandlet couldn't find all the specified manifest dependencies.")); return -1; } //The main array of files to work from. TArray< FString > PackageFileNamesToProcess; TArray<FString> PackageFilesNotInIncludePath; TArray<FString> PackageFilesInExcludePath; TArray<FString> PackageFilesExcludedByClass; //Fill the list of packages to work from. uint8 PackageFilter = NORMALIZE_DefaultFlags; TArray<FString> Unused; for ( int32 PackageFilenameWildcardIdx = 0; PackageFilenameWildcardIdx < PackageFileNameFilters.Num(); PackageFilenameWildcardIdx++ ) { const bool IsAssetPackage = PackageFileNameFilters[PackageFilenameWildcardIdx] == ( FString( TEXT("*") )+ FPackageName::GetAssetPackageExtension() ); TArray<FString> PackageFiles; if ( !NormalizePackageNames( Unused, PackageFiles, PackageFileNameFilters[PackageFilenameWildcardIdx], PackageFilter) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("No packages found with extension %i: '%s'"), PackageFilenameWildcardIdx, *PackageFileNameFilters[PackageFilenameWildcardIdx]); continue; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("Found %i packages with extension %i: '%s'"), PackageFiles.Num(), PackageFilenameWildcardIdx, *PackageFileNameFilters[PackageFilenameWildcardIdx]); } //Run through all the files found and add any that pass the include, exclude and filter constraints to OrderedPackageFilesToLoad for (FString& PackageFile : PackageFiles) { PackageFile = FPaths::ConvertRelativePathToFull(PackageFile); bool bExclude = false; //Ensure it matches the include paths if there are some. for (FString& IncludePath : IncludePathFilters) { bExclude = true; if( PackageFile.MatchesWildcard(IncludePath) ) { bExclude = false; break; } } if ( bExclude ) { PackageFilesNotInIncludePath.Add(PackageFile); } //Ensure it does not match the exclude paths if there are some. for (const FString& ExcludePath : ExcludePathFilters) { if (PackageFile.MatchesWildcard(ExcludePath)) { bExclude = true; PackageFilesInExcludePath.Add(PackageFile); break; } } //Check that this is not on the list of packages that we don't care about e.g. textures. if ( !bExclude && IsAssetPackage && LongPackageNamesToExclude.Contains( PackageFile ) ) { bExclude = true; PackageFilesExcludedByClass.Add(PackageFile); } //If we haven't failed one of the above checks, add it to the array of packages to process. if(!bExclude) { PackageFileNamesToProcess.Add(PackageFile); } } } if ( PackageFileNamesToProcess.Num() == 0 ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No files found or none passed the include/exclude criteria.")); } bool bSkipGatherCache = FParse::Param(FCommandLine::Get(), TEXT("SkipGatherCache")); if (!bSkipGatherCache) { GetBoolFromConfig(*SectionName, TEXT("SkipGatherCache"), bSkipGatherCache, GatherTextConfigPath); } UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("SkipGatherCache: %s"), bSkipGatherCache ? TEXT("true") : TEXT("false")); TArray< FString > PackageFileNamesToLoad; for (FString& PackageFile : PackageFileNamesToProcess) { TScopedPointer< FArchive > FileReader( IFileManager::Get().CreateFileReader( *PackageFile ) ); if( FileReader ) { // Read package file summary from the file FPackageFileSummary PackageFileSummary; (*FileReader) << PackageFileSummary; bool MustLoadForGather = false; // Have we been asked to skip the cache of text that exists in the header of newer packages? if (bSkipGatherCache && PackageFileSummary.GetFileVersionUE4() >= VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { // Fallback on the old package flag check. if (PackageFileSummary.PackageFlags & PKG_RequiresLocalizationGather) { MustLoadForGather = true; } } const FCustomVersion* const EditorVersion = PackageFileSummary.GetCustomVersionContainer().GetVersion(FEditorObjectVersion::GUID); // Packages not resaved since localization gathering flagging was added to packages must be loaded. if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_PACKAGE_REQUIRES_LOCALIZATION_GATHER_FLAGGING) { MustLoadForGather = true; } // Package not resaved since gatherable text data was added to package headers must be loaded, since their package header won't contain pregathered text data. else if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { // Fallback on the old package flag check. if (PackageFileSummary.PackageFlags & PKG_RequiresLocalizationGather) { MustLoadForGather = true; } } else if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_DIALOGUE_WAVE_NAMESPACE_AND_CONTEXT_CHANGES) { IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); TArray<FAssetData> AssetDataInPackage; AssetRegistry.GetAssetsByPackageName(*FPackageName::FilenameToLongPackageName(PackageFile), AssetDataInPackage); for (const FAssetData& AssetData : AssetDataInPackage) { if (AssetData.AssetClass == UDialogueWave::StaticClass()->GetFName()) { MustLoadForGather = true; } } } // Add package to list of packages to load fully and process. if (MustLoadForGather) { PackageFileNamesToLoad.Add(PackageFile); } // Process immediately packages that don't require loading to process. else if (PackageFileSummary.GatherableTextDataOffset > 0) { FileReader->Seek(PackageFileSummary.GatherableTextDataOffset); TArray<FGatherableTextData> GatherableTextDataArray; GatherableTextDataArray.SetNum(PackageFileSummary.GatherableTextDataCount); for (int32 GatherableTextDataIndex = 0; GatherableTextDataIndex < PackageFileSummary.GatherableTextDataCount; ++GatherableTextDataIndex) { (*FileReader) << GatherableTextDataArray[GatherableTextDataIndex]; } ProcessGatherableTextDataArray(PackageFile, GatherableTextDataArray); } } } CollectGarbage(RF_NoFlags); //Now go through the remaining packages in the main array and process them in batches. int32 PackagesPerBatchCount = 100; TArray< UPackage* > LoadedPackages; TArray< FString > LoadedPackageFileNames; TArray< FString > FailedPackageFileNames; TArray< UPackage* > LoadedPackagesToProcess; const int32 PackageCount = PackageFileNamesToLoad.Num(); const int32 BatchCount = PackageCount / PackagesPerBatchCount + (PackageCount % PackagesPerBatchCount > 0 ? 1 : 0); // Add an extra batch for any remainder if necessary if(PackageCount > 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loading %i packages in %i batches of %i."), PackageCount, BatchCount, PackagesPerBatchCount); } FLoadPackageLogOutputRedirector LogOutputRedirector; //Load the packages in batches int32 PackageIndex = 0; for( int32 BatchIndex = 0; BatchIndex < BatchCount; ++BatchIndex ) { int32 PackagesInThisBatch = 0; int32 FailuresInThisBatch = 0; for( ; PackageIndex < PackageCount && PackagesInThisBatch < PackagesPerBatchCount; ++PackageIndex ) { FString PackageFileName = PackageFileNamesToLoad[PackageIndex]; UE_LOG(LogGatherTextFromAssetsCommandlet, Verbose, TEXT("Loading package: '%s'."), *PackageFileName); UPackage *Package = nullptr; { FString LongPackageName; if (!FPackageName::TryConvertFilenameToLongPackageName(PackageFileName, LongPackageName)) { LongPackageName = FPaths::GetCleanFilename(PackageFileName); } FLoadPackageLogOutputRedirector::FScopedCapture ScopedCapture(&LogOutputRedirector, LongPackageName); Package = LoadPackage( NULL, *PackageFileName, LOAD_NoWarn | LOAD_Quiet ); } if( Package ) { LoadedPackages.Add(Package); LoadedPackageFileNames.Add(PackageFileName); // Because packages may not have been resaved after this flagging was implemented, we may have added packages to load that weren't flagged - potential false positives. // The loading process should have reflagged said packages so that only true positives will have this flag. if( Package->RequiresLocalizationGather() ) { LoadedPackagesToProcess.Add( Package ); } } else { FailedPackageFileNames.Add( PackageFileName ); ++FailuresInThisBatch; continue; } ++PackagesInThisBatch; } UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loaded %i packages in batch %i of %i. %i failed."), PackagesInThisBatch, BatchIndex + 1, BatchCount, FailuresInThisBatch); ProcessPackages(LoadedPackagesToProcess); LoadedPackagesToProcess.Empty(PackagesPerBatchCount); if( bFixBroken ) { for( int32 LoadedPackageIndex=0; LoadedPackageIndex < LoadedPackages.Num() ; ++LoadedPackageIndex ) { UPackage *Package = LoadedPackages[LoadedPackageIndex]; const FString PackageName = LoadedPackageFileNames[LoadedPackageIndex]; //Todo - link with source control. if( Package ) { if( Package->IsDirty() ) { if( SavePackageHelper( Package, *PackageName ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Saved Package %s."),*PackageName); } else { //TODO - Work out how to integrate with source control. The code from the source gatherer doesn't work. UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Could not save package %s. Probably due to source control. "),*PackageName); } } } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Failed to find one of the loaded packages.")); } } } CollectGarbage(RF_NoFlags); LoadedPackages.Empty(PackagesPerBatchCount); LoadedPackageFileNames.Empty(PackagesPerBatchCount); } return 0; }
EReimportResult::Type UReimportFbxSceneFactory::Reimport(UObject* Obj) { ReimportData = GetFbxSceneImportData(Obj); if (!ReimportData) { return EReimportResult::Failed; } //We will call other factory store the filename value since UFactory::CurrentFilename is static FbxImportFileName = ReimportData->SourceFbxFile; UnFbx::FFbxImporter* FbxImporter = UnFbx::FFbxImporter::GetInstance(); UnFbx::FFbxLoggerSetter Logger(FbxImporter); GWarn->BeginSlowTask(NSLOCTEXT("FbxSceneReImportFactory", "BeginReImportingFbxSceneTask", "ReImporting FBX scene"), true); GlobalImportSettings = FbxImporter->GetImportOptions(); //Fill the original options for (auto kvp : ReimportData->NameOptionsMap) { if (kvp.Key.Compare(DefaultOptionName) == 0) { SFbxSceneOptionWindow::CopyFbxOptionsToFbxOptions(kvp.Value, GlobalImportSettings); NameOptionsMap.Add(kvp.Key, GlobalImportSettings); } else { NameOptionsMap.Add(kvp.Key, kvp.Value); } } //Always convert the scene GlobalImportSettings->bConvertScene = true; GlobalImportSettings->bImportScene = ReimportData->bImportScene; //Read the fbx and store the hierarchy's information so we can reuse it after importing all the model in the fbx file if (!FbxImporter->ImportFromFile(*FbxImportFileName, FPaths::GetExtension(FbxImportFileName))) { // Log the error message and fail the import. GWarn->Log(ELogVerbosity::Error, FbxImporter->GetErrorMessage()); FbxImporter->ReleaseScene(); FbxImporter = nullptr; GWarn->EndSlowTask(); return EReimportResult::Failed; } FString PackageName = ""; Obj->GetOutermost()->GetName(PackageName); Path = FPaths::GetPath(PackageName); UnFbx::FbxSceneInfo SceneInfo; //Read the scene and found all instance with their scene information. FbxImporter->GetSceneInfo(FbxImportFileName, SceneInfo); //Convert old structure to the new scene export structure TSharedPtr<FFbxSceneInfo> SceneInfoPtr = ConvertSceneInfo(&SceneInfo); //Get import material info ExtractMaterialInfo(FbxImporter, SceneInfoPtr); if (!ReimportData->bCreateFolderHierarchy) { for (TSharedPtr<FFbxMeshInfo> MeshInfo : SceneInfoPtr->MeshInfo) { FString AssetName = Path + TEXT("/") + MeshInfo->Name; MeshInfo->SetOriginalImportPath(AssetName); FString OriginalFullImportName = PackageTools::SanitizePackageName(AssetName); OriginalFullImportName = OriginalFullImportName + TEXT(".") + PackageTools::SanitizePackageName(MeshInfo->Name); MeshInfo->SetOriginalFullImportName(OriginalFullImportName); } } else { TSet<uint64> AssetPathDone; FString AssetPath = Path; for (TSharedPtr<FFbxNodeInfo> NodeInfo : SceneInfoPtr->HierarchyInfo) { //Iterate the hierarchy and build the original path RecursivelyCreateOriginalPath(FbxImporter, NodeInfo, AssetPath, AssetPathDone); } } FillSceneHierarchyPath(SceneInfoPtr); FbxSceneReimportStatusMap MeshStatusMap; FbxSceneReimportStatusMap NodeStatusMap; bool bCanReimportHierarchy = ReimportData->HierarchyType == (int32)EFBXSceneOptionsCreateHierarchyType::FBXSOCHT_CreateBlueprint && !ReimportData->BluePrintFullName.IsEmpty(); if (!GetFbxSceneReImportOptions(FbxImporter , SceneInfoPtr , ReimportData->SceneInfoSourceData , GlobalImportSettings , SceneImportOptions , SceneImportOptionsStaticMesh , NameOptionsMap , MeshStatusMap , NodeStatusMap , bCanReimportHierarchy , Path)) { //User cancel the scene import FbxImporter->ReleaseScene(); FbxImporter = nullptr; GlobalImportSettings = nullptr; GWarn->EndSlowTask(); return EReimportResult::Cancelled; } GlobalImportSettingsReference = new UnFbx::FBXImportOptions(); SFbxSceneOptionWindow::CopyFbxOptionsToFbxOptions(GlobalImportSettings, GlobalImportSettingsReference); //Overwrite the reimport asset data with the new data ReimportData->SceneInfoSourceData = SceneInfoPtr; ReimportData->SourceFbxFile = FPaths::ConvertRelativePathToFull(FbxImportFileName); ReimportData->bImportScene = GlobalImportSettingsReference->bImportScene; //Copy the options map ReimportData->NameOptionsMap.Reset(); for (auto kvp : NameOptionsMap) { ReimportData->NameOptionsMap.Add(kvp.Key, kvp.Value); } FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry"); TArray<FAssetData> AssetDataToDelete; for (TSharedPtr<FFbxMeshInfo> MeshInfo : SceneInfoPtr->MeshInfo) { //Delete all the delete asset if (!MeshStatusMap.Contains(MeshInfo->OriginalImportPath)) { continue; } EFbxSceneReimportStatusFlags MeshStatus = *(MeshStatusMap.Find(MeshInfo->OriginalImportPath)); if ((MeshStatus & EFbxSceneReimportStatusFlags::Removed) == EFbxSceneReimportStatusFlags::None || (MeshStatus & EFbxSceneReimportStatusFlags::ReimportAsset) == EFbxSceneReimportStatusFlags::None) { continue; } //Make sure we load all package that will be deleted UPackage* PkgExist = LoadPackage(nullptr, *(MeshInfo->GetImportPath()), LOAD_Verify | LOAD_NoWarn); if (PkgExist == nullptr) { continue; } PkgExist->FullyLoad(); //Find the asset AssetDataToDelete.Add(AssetRegistryModule.Get().GetAssetByObjectPath(FName(*(MeshInfo->GetFullImportName())))); } AllNewAssets.Empty(); AssetToSyncContentBrowser.Empty(); EReimportResult::Type ReimportResult = EReimportResult::Succeeded; //Reimport and add asset for (TSharedPtr<FFbxMeshInfo> MeshInfo : SceneInfoPtr->MeshInfo) { if (!MeshStatusMap.Contains(MeshInfo->OriginalImportPath)) { continue; } EFbxSceneReimportStatusFlags MeshStatus = *(MeshStatusMap.Find(MeshInfo->OriginalImportPath)); //Set the import status for the next reimport MeshInfo->bImportAttribute = (MeshStatus & EFbxSceneReimportStatusFlags::ReimportAsset) != EFbxSceneReimportStatusFlags::None; if ((MeshStatus & EFbxSceneReimportStatusFlags::Removed) != EFbxSceneReimportStatusFlags::None || (MeshStatus & EFbxSceneReimportStatusFlags::ReimportAsset) == EFbxSceneReimportStatusFlags::None) { continue; } if (((MeshStatus & EFbxSceneReimportStatusFlags::Same) != EFbxSceneReimportStatusFlags::None || (MeshStatus & EFbxSceneReimportStatusFlags::Added) != EFbxSceneReimportStatusFlags::None) && (MeshStatus & EFbxSceneReimportStatusFlags::FoundContentBrowserAsset) != EFbxSceneReimportStatusFlags::None) { //Reimport over the old asset if (!MeshInfo->bIsSkelMesh) { ReimportResult = ReimportStaticMesh(FbxImporter, MeshInfo); } else { //TODO reimport skeletal mesh } } else if ((MeshStatus & EFbxSceneReimportStatusFlags::Added) != EFbxSceneReimportStatusFlags::None || (MeshStatus & EFbxSceneReimportStatusFlags::Same) != EFbxSceneReimportStatusFlags::None) { //Create a package for this node //Get Parent hierarchy name to create new package path ReimportResult = ImportStaticMesh(FbxImporter, MeshInfo, SceneInfoPtr); } } //Put back the default option in the static mesh import data, so next import will have those last import option SFbxSceneOptionWindow::CopyFbxOptionsToFbxOptions(GlobalImportSettingsReference, GlobalImportSettings); SFbxSceneOptionWindow::CopyFbxOptionsToStaticMeshOptions(GlobalImportSettingsReference, SceneImportOptionsStaticMesh); SceneImportOptionsStaticMesh->FillStaticMeshInmportData(StaticMeshImportData, SceneImportOptions); StaticMeshImportData->SaveConfig(); //Update the blueprint UBlueprint *ReimportBlueprint = nullptr; if (bCanReimportHierarchy && GlobalImportSettingsReference->bImportScene) { ReimportBlueprint = UpdateOriginalBluePrint(ReimportData->BluePrintFullName, &NodeStatusMap, SceneInfoPtr, ReimportData->SceneInfoSourceData, AssetDataToDelete); } //Remove the deleted meshinfo node from the reimport data TArray<TSharedPtr<FFbxMeshInfo>> ToRemoveHierarchyNode; for (TSharedPtr<FFbxMeshInfo> MeshInfo : ReimportData->SceneInfoSourceData->MeshInfo) { EFbxSceneReimportStatusFlags MeshStatus = *(MeshStatusMap.Find(MeshInfo->OriginalImportPath)); if ((MeshStatus & EFbxSceneReimportStatusFlags::Removed) != EFbxSceneReimportStatusFlags::None) { ToRemoveHierarchyNode.Add(MeshInfo); } } for (TSharedPtr<FFbxMeshInfo> MeshInfo : ToRemoveHierarchyNode) { ReimportData->SceneInfoSourceData->MeshInfo.Remove(MeshInfo); } ReimportData->Modify(); ReimportData->PostEditChange(); //Make sure the content browser is in sync before we delete FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); ContentBrowserModule.Get().SyncBrowserToAssets(AssetToSyncContentBrowser); if (AssetDataToDelete.Num() > 0) { bool AbortDelete = false; if (ReimportBlueprint != nullptr) { //Save the blueprint to avoid reference from the old blueprint FAssetData ReimportBlueprintAsset(ReimportBlueprint); TArray<UPackage*> Packages; Packages.Add(ReimportBlueprintAsset.GetPackage()); FEditorFileUtils::PromptForCheckoutAndSave(Packages, false, false); //Make sure the Asset registry is up to date after the save TArray<FString> Paths; Paths.Add(ReimportBlueprintAsset.PackagePath.ToString()); AssetRegistryModule.Get().ScanPathsSynchronous(Paths, true); } if (!AbortDelete) { //Delete the asset and use the normal dialog to make sure the user understand he will remove some content //The user can decide to cancel the delete or not. This will not interrupt the reimport process //The delete is done at the end because we want to remove the blueprint reference before deleting object ObjectTools::DeleteAssets(AssetDataToDelete, true); } } //Make sure the content browser is in sync ContentBrowserModule.Get().SyncBrowserToAssets(AssetToSyncContentBrowser); AllNewAssets.Empty(); GlobalImportSettings = nullptr; GlobalImportSettingsReference = nullptr; FbxImporter->ReleaseScene(); FbxImporter = nullptr; GWarn->EndSlowTask(); return EReimportResult::Succeeded; }
void UUnrealEdEngine::Init(IEngineLoop* InEngineLoop) { Super::Init(InEngineLoop); // Build databases used by source code navigation FSourceCodeNavigation::Initialize(); PackageAutoSaver.Reset(new FPackageAutoSaver); PackageAutoSaver->LoadRestoreFile(); #if !UE_BUILD_DEBUG if( !GEditorSettingsIni.IsEmpty() ) { // We need the game agnostic ini for this code PerformanceMonitor = new FPerformanceMonitor; } #endif // Register for the package dirty state updated callback to catch packages that have been modified and need to be checked out. UPackage::PackageDirtyStateChangedEvent.AddUObject(this, &UUnrealEdEngine::OnPackageDirtyStateUpdated); // Register to the PostGarbageCollect delegate, as we want to use this to trigger the RefreshAllBroweser delegate from // here rather then from Core FCoreUObjectDelegates::PostGarbageCollect.AddUObject(this, &UUnrealEdEngine::OnPostGarbageCollect); // register to color picker changed event and trigger RedrawAllViewports when that happens */ FCoreDelegates::ColorPickerChanged.AddUObject(this, &UUnrealEdEngine::OnColorPickerChanged); // register windows message pre and post handler FEditorSupportDelegates::PreWindowsMessage.AddUObject(this, &UUnrealEdEngine::OnPreWindowsMessage); FEditorSupportDelegates::PostWindowsMessage.AddUObject(this, &UUnrealEdEngine::OnPostWindowsMessage); // Initialize the snap manager FSnappingUtils::InitEditorSnappingTools(); // Register for notification of volume changes AVolume::GetOnVolumeShapeChangedDelegate().AddStatic(&FBSPOps::HandleVolumeShapeChanged); // InitBuilderBrush( GWorld ); // Iterate over all always fully loaded packages and load them. if (!IsRunningCommandlet()) { for( int32 PackageNameIndex=0; PackageNameIndex<PackagesToBeFullyLoadedAtStartup.Num(); PackageNameIndex++ ) { const FString& PackageName = PackagesToBeFullyLoadedAtStartup[PackageNameIndex]; // Load package if it's found in the package file cache. if( FPackageName::DoesPackageExist( PackageName ) ) { LoadPackage( NULL, *PackageName, LOAD_None ); } } } // Populate the data structures related to the sprite category visibility feature for use elsewhere in the editor later TArray<FSpriteCategoryInfo> SortedSpriteInfo; UUnrealEdEngine::MakeSortedSpriteInfo(SortedSpriteInfo); // Iterate over the sorted list, constructing a mapping of unlocalized categories to the index the localized category // resides in. This is an optimization to prevent having to localize values repeatedly. for( int32 InfoIndex = 0; InfoIndex < SortedSpriteInfo.Num(); ++InfoIndex ) { const FSpriteCategoryInfo& SpriteInfo = SortedSpriteInfo[InfoIndex]; SpriteIDToIndexMap.Add( SpriteInfo.Category, InfoIndex ); } if (FPaths::IsProjectFilePathSet()) { AutoReimportManager = NewObject<UAutoReimportManager>(); AutoReimportManager->Initialize(); GetMutableDefault<UEditorLoadingSavingSettings>()->CheckSourceControlCompatability(); } // register details panel customizations if (!HasAnyFlags(RF_ClassDefaultObject)) { FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor"); PropertyModule.RegisterCustomClassLayout("EditorLoadingSavingSettings", FOnGetDetailCustomizationInstance::CreateStatic(&FEditorLoadingSavingSettingsCustomization::MakeInstance)); PropertyModule.RegisterCustomClassLayout("GameMapsSettings", FOnGetDetailCustomizationInstance::CreateStatic(&FGameMapsSettingsCustomization::MakeInstance)); PropertyModule.RegisterCustomClassLayout("LevelEditorPlaySettings", FOnGetDetailCustomizationInstance::CreateStatic(&FLevelEditorPlaySettingsCustomization::MakeInstance)); PropertyModule.RegisterCustomClassLayout("ProjectPackagingSettings", FOnGetDetailCustomizationInstance::CreateStatic(&FProjectPackagingSettingsCustomization::MakeInstance)); } UEditorExperimentalSettings const* ExperimentalSettings = GetDefault<UEditorExperimentalSettings>(); ECookInitializationFlags BaseCookingFlags = ECookInitializationFlags::AutoTick | ECookInitializationFlags::AsyncSave | ECookInitializationFlags::Compressed; BaseCookingFlags |= ExperimentalSettings->bIterativeCookingForLaunchOn ? ECookInitializationFlags::Iterative : ECookInitializationFlags::None; bool bEnableCookOnTheSide = false; GConfig->GetBool(TEXT("/Script/UnrealEd.CookerSettings"), TEXT("bEnableCookOnTheSide"), bEnableCookOnTheSide, GEngineIni); if ( bEnableCookOnTheSide ) { CookServer = NewObject<UCookOnTheFlyServer>(); CookServer->Initialize( ECookMode::CookOnTheFlyFromTheEditor, BaseCookingFlags ); CookServer->StartNetworkFileServer( false ); FCoreUObjectDelegates::OnObjectPropertyChanged.AddUObject(CookServer, &UCookOnTheFlyServer::OnObjectPropertyChanged); FCoreUObjectDelegates::OnObjectModified.AddUObject(CookServer, &UCookOnTheFlyServer::OnObjectModified); FCoreUObjectDelegates::OnObjectSaved.AddUObject( CookServer, &UCookOnTheFlyServer::OnObjectSaved ); } else if ( !ExperimentalSettings->bDisableCookInEditor) { CookServer = NewObject<UCookOnTheFlyServer>(); CookServer->Initialize( ECookMode::CookByTheBookFromTheEditor, BaseCookingFlags ); FCoreUObjectDelegates::OnObjectPropertyChanged.AddUObject(CookServer, &UCookOnTheFlyServer::OnObjectPropertyChanged); FCoreUObjectDelegates::OnObjectModified.AddUObject(CookServer, &UCookOnTheFlyServer::OnObjectModified); FCoreUObjectDelegates::OnObjectSaved.AddUObject( CookServer, &UCookOnTheFlyServer::OnObjectSaved ); } }
void FLevelCollectionModel::SCCDiffAgainstDepot(const FLevelModelList& InList, UEditorEngine* InEditor) { // Load the asset registry module FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools"); ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); // Iterate over each selected asset for (auto It = InList.CreateConstIterator(); It; ++It) { ULevel* Level = (*It)->GetLevelObject(); if (Level == NULL) { return; } UPackage* OriginalPackage = Level->GetOutermost(); FString PackageName = OriginalPackage->GetName(); // Make sure our history is up to date auto UpdateStatusOperation = ISourceControlOperation::Create<FUpdateStatus>(); UpdateStatusOperation->SetUpdateHistory(true); SourceControlProvider.Execute(UpdateStatusOperation, OriginalPackage); // Get the SCC state FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState( OriginalPackage, EStateCacheUsage::Use ); // If the level is in SCC. if (SourceControlState.IsValid() && SourceControlState->IsSourceControlled()) { // Get the file name of package FString RelativeFileName; if(FPackageName::DoesPackageExist(PackageName, NULL, &RelativeFileName)) { if (SourceControlState->GetHistorySize() > 0) { auto Revision = SourceControlState->GetHistoryItem(0); check(Revision.IsValid()); // Get the head revision of this package from source control FString AbsoluteFileName = FPaths::ConvertRelativePathToFull(RelativeFileName); FString TempFileName; if (Revision->Get(TempFileName)) { // Forcibly disable compile on load in case we are loading old blueprints that might try to update/compile TGuardValue<bool> DisableCompileOnLoad(GForceDisableBlueprintCompileOnLoad, true); // Try and load that package FText NotMapReason; UPackage* OldPackage = LoadPackage(NULL, *TempFileName, LOAD_None); if(OldPackage != NULL && InEditor->PackageIsAMapFile(*TempFileName, NotMapReason)) { /* Set the revision information*/ UPackage* Package = OriginalPackage; FRevisionInfo OldRevision; OldRevision.Changelist = Revision->GetCheckInIdentifier(); OldRevision.Date = Revision->GetDate(); OldRevision.Revision = Revision->GetRevision(); FRevisionInfo NewRevision; NewRevision.Revision = TEXT(""); // Dump assets to temp text files FString OldTextFilename = AssetToolsModule.Get().DumpAssetToTempFile(OldPackage); FString NewTextFilename = AssetToolsModule.Get().DumpAssetToTempFile(OriginalPackage); FString DiffCommand = GetDefault<UEditorLoadingSavingSettings>()->TextDiffToolPath.FilePath; AssetToolsModule.Get().CreateDiffProcess(DiffCommand, OldTextFilename, NewTextFilename); AssetToolsModule.Get().DiffAssets(OldPackage, OriginalPackage, OldRevision, NewRevision); } } } } } } }
UBlueprint *UReimportFbxSceneFactory::UpdateOriginalBluePrint(FString &BluePrintFullName, void* VoidNodeStatusMapPtr, TSharedPtr<FFbxSceneInfo> SceneInfoPtr, TSharedPtr<FFbxSceneInfo> SceneInfoOriginalPtr, TArray<FAssetData> &AssetDataToDelete) { if (!SceneInfoPtr.IsValid() || VoidNodeStatusMapPtr == nullptr || !SceneInfoOriginalPtr.IsValid() || BluePrintFullName.IsEmpty()) { return nullptr; } FbxSceneReimportStatusMapPtr NodeStatusMapPtr = (FbxSceneReimportStatusMapPtr)VoidNodeStatusMapPtr; //Find the BluePrint FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry"); FAssetData BlueprintAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(FName(*(BluePrintFullName))); UPackage* PkgExist = LoadPackage(nullptr, *BlueprintAssetData.PackageName.ToString(), LOAD_Verify | LOAD_NoWarn); if (PkgExist == nullptr) { return nullptr; } //Load the package before searching the asset PkgExist->FullyLoad(); UBlueprint* BluePrint = FindObjectSafe<UBlueprint>(ANY_PACKAGE, *BluePrintFullName); if (BluePrint == nullptr) { return nullptr; } //Close all editor that edit this blueprint FAssetEditorManager::Get().CloseAllEditorsForAsset(BluePrint); //Set the import status for the next reimport for (TSharedPtr<FFbxNodeInfo> NodeInfo : SceneInfoPtr->HierarchyInfo) { if (!NodeStatusMapPtr->Contains(NodeInfo->NodeHierarchyPath)) continue; EFbxSceneReimportStatusFlags NodeStatus = *(NodeStatusMapPtr->Find(NodeInfo->NodeHierarchyPath)); NodeInfo->bImportNode = (NodeStatus & EFbxSceneReimportStatusFlags::ReimportAsset) != EFbxSceneReimportStatusFlags::None; } //Add back the component that was in delete state but no flag for reimport for (TSharedPtr<FFbxNodeInfo> OriginalNodeInfo : SceneInfoOriginalPtr->HierarchyInfo) { if (!NodeStatusMapPtr->Contains(OriginalNodeInfo->NodeHierarchyPath)) { continue; } EFbxSceneReimportStatusFlags NodeStatus = *(NodeStatusMapPtr->Find(OriginalNodeInfo->NodeHierarchyPath)); if (OriginalNodeInfo->bImportNode != true || (NodeStatus & EFbxSceneReimportStatusFlags::ReimportAsset) != EFbxSceneReimportStatusFlags::None) { continue; } //Clear the child OriginalNodeInfo->Childrens.Empty(); //hook the node to the new hierarchy parent bool bFoundParent = false; if (OriginalNodeInfo->ParentNodeInfo.IsValid()) { int32 InsertIndex = 0; for (TSharedPtr<FFbxNodeInfo> NodeInfo : SceneInfoPtr->HierarchyInfo) { InsertIndex++; if (NodeInfo->bImportNode && NodeInfo->NodeHierarchyPath.Compare(OriginalNodeInfo->ParentNodeInfo->NodeHierarchyPath) == 0) { OriginalNodeInfo->ParentNodeInfo = NodeInfo; NodeInfo->Childrens.Add(OriginalNodeInfo); SceneInfoPtr->HierarchyInfo.Insert(OriginalNodeInfo, InsertIndex); bFoundParent = true; break; } } } if (!bFoundParent) { //Insert after the root node OriginalNodeInfo->ParentNodeInfo = nullptr; SceneInfoPtr->HierarchyInfo.Insert(OriginalNodeInfo, 1); } } //Create a brand new actor with the correct component hierarchy then replace the existing blueprint //This function is using the bImportNode flag not the EFbxSceneReimportStatusFlags AActor *HierarchyActor = CreateActorComponentsHierarchy(SceneInfoPtr); if (HierarchyActor != nullptr) { //Modify the current blueprint to reflect the new actor //Clear all nodes by removing all root node TArray<USCS_Node*> BluePrintRootNodes = BluePrint->SimpleConstructionScript->GetRootNodes(); for(USCS_Node* RootNode : BluePrintRootNodes) { RemoveChildNodeRecursively(BluePrint->SimpleConstructionScript, RootNode); } //Create the new nodes from the hierarchy actor FKismetEditorUtilities::AddComponentsToBlueprint(BluePrint, HierarchyActor->GetInstanceComponents()); //Cleanup the temporary actor HierarchyActor->Destroy(); BluePrint->Modify(); BluePrint->PostEditChange(); AssetToSyncContentBrowser.Add(BluePrint); return BluePrint; } return nullptr; }
EReimportResult::Type UReimportFbxSceneFactory::ReimportStaticMesh(void* VoidFbxImporter, TSharedPtr<FFbxMeshInfo> MeshInfo) { UnFbx::FFbxImporter* FbxImporter = (UnFbx::FFbxImporter*)VoidFbxImporter; //Find the UObject associate with this MeshInfo UPackage* PkgExist = LoadPackage(nullptr, *(MeshInfo->GetImportPath()), LOAD_Verify | LOAD_NoWarn); if (PkgExist != nullptr) { PkgExist->FullyLoad(); } FString AssetName = MeshInfo->GetFullImportName(); UStaticMesh* Mesh = FindObjectSafe<UStaticMesh>(ANY_PACKAGE, *AssetName); if (Mesh == nullptr) { //We reimport only static mesh here FbxImporter->AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(FText::FromString("Reimport Mesh {0} fail, the original staicmesh in the content browser cannot be load."), FText::FromString(MeshInfo->GetImportPath()))), FName(TEXT("Reimport Fbx Scene"))); return EReimportResult::Failed; } //Copy default options to StaticMeshImportData SFbxSceneOptionWindow::CopyFbxOptionsToStaticMeshOptions(GlobalImportSettingsReference, SceneImportOptionsStaticMesh); SceneImportOptionsStaticMesh->FillStaticMeshInmportData(StaticMeshImportData, SceneImportOptions); UnFbx::FBXImportOptions* OverrideImportSettings = GetOptionsFromName(MeshInfo->OptionName); if (OverrideImportSettings != nullptr) { SFbxSceneOptionWindow::CopyFbxOptionsToFbxOptions(OverrideImportSettings, GlobalImportSettings); SFbxSceneOptionWindow::CopyFbxOptionsToStaticMeshOptions(OverrideImportSettings, SceneImportOptionsStaticMesh); } else { SFbxSceneOptionWindow::CopyFbxOptionsToFbxOptions(GlobalImportSettingsReference, GlobalImportSettings); SFbxSceneOptionWindow::CopyFbxOptionsToStaticMeshOptions(GlobalImportSettingsReference, SceneImportOptionsStaticMesh); } SceneImportOptionsStaticMesh->FillStaticMeshInmportData(StaticMeshImportData, SceneImportOptions); FbxImporter->ApplyTransformSettingsToFbxNode(FbxImporter->Scene->GetRootNode(), StaticMeshImportData); const TArray<UAssetUserData*>* UserData = Mesh->GetAssetUserDataArray(); TArray<UAssetUserData*> UserDataCopy; if (UserData) { for (int32 Idx = 0; Idx < UserData->Num(); Idx++) { UserDataCopy.Add((UAssetUserData*)StaticDuplicateObject((*UserData)[Idx], GetTransientPackage())); } } // preserve settings in navcollision subobject UNavCollision* NavCollision = Mesh->NavCollision ? (UNavCollision*)StaticDuplicateObject(Mesh->NavCollision, GetTransientPackage()) : nullptr; // preserve extended bound settings const FVector PositiveBoundsExtension = Mesh->PositiveBoundsExtension; const FVector NegativeBoundsExtension = Mesh->NegativeBoundsExtension; Mesh = FbxImporter->ReimportSceneStaticMesh(MeshInfo->UniqueId, Mesh, StaticMeshImportData); if (Mesh != nullptr) { //Put back the new mesh data since the reimport is putting back the original import data SceneImportOptionsStaticMesh->FillStaticMeshInmportData(StaticMeshImportData, SceneImportOptions); Mesh->AssetImportData = StaticMeshImportData; // Copy user data to newly created mesh for (int32 Idx = 0; Idx < UserDataCopy.Num(); Idx++) { UserDataCopy[Idx]->Rename(nullptr, Mesh, REN_DontCreateRedirectors | REN_DoNotDirty); Mesh->AddAssetUserData(UserDataCopy[Idx]); } if (NavCollision) { Mesh->NavCollision = NavCollision; NavCollision->Rename(nullptr, Mesh, REN_DontCreateRedirectors | REN_DoNotDirty); } // Restore bounds extension settings Mesh->PositiveBoundsExtension = PositiveBoundsExtension; Mesh->NegativeBoundsExtension = NegativeBoundsExtension; Mesh->AssetImportData->Update(FbxImportFileName); // Try to find the outer package so we can dirty it up if (Mesh->GetOutermost()) { Mesh->GetOutermost()->MarkPackageDirty(); } else { Mesh->MarkPackageDirty(); } AllNewAssets.Add(MeshInfo, Mesh); AssetToSyncContentBrowser.Add(Mesh); } else { return EReimportResult::Failed; } return EReimportResult::Succeeded; }
int32 UDerivedDataCacheCommandlet::Main( const FString& Params ) { TArray<FString> Tokens, Switches; ParseCommandLine(*Params, Tokens, Switches); bool bFillCache = Switches.Contains("FILL"); // do the equivalent of a "loadpackage -all" to fill the DDC bool bStartupOnly = Switches.Contains("STARTUPONLY"); // regardless of any other flags, do not iterate packages // Subsets for parallel processing uint32 SubsetMod = 0; uint32 SubsetTarget = MAX_uint32; FParse::Value(*Params, TEXT("SubsetMod="), SubsetMod); FParse::Value(*Params, TEXT("SubsetTarget="), SubsetTarget); bool bDoSubset = SubsetMod > 0 && SubsetTarget < SubsetMod; double FindProcessedPackagesTime = 0.0; double GCTime = 0.0; if (!bStartupOnly && bFillCache) { FCoreDelegates::PackageCreatedForLoad.AddUObject(this, &UDerivedDataCacheCommandlet::MaybeMarkPackageAsAlreadyLoaded); TArray<FString> FilesInPath; Tokens.Empty(2); Tokens.Add(FString("*") + FPackageName::GetAssetPackageExtension()); Tokens.Add(FString("*") + FPackageName::GetMapPackageExtension()); uint8 PackageFilter = NORMALIZE_DefaultFlags; if ( Switches.Contains(TEXT("MAPSONLY")) ) { PackageFilter |= NORMALIZE_ExcludeContentPackages; } if ( !Switches.Contains(TEXT("DEV")) ) { PackageFilter |= NORMALIZE_ExcludeDeveloperPackages; } // assume the first token is the map wildcard/pathname TArray<FString> Unused; for ( int32 TokenIndex = 0; TokenIndex < Tokens.Num(); TokenIndex++ ) { TArray<FString> TokenFiles; if ( !NormalizePackageNames( Unused, TokenFiles, Tokens[TokenIndex], PackageFilter) ) { UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("No packages found for parameter %i: '%s'"), TokenIndex, *Tokens[TokenIndex]); continue; } FilesInPath += TokenFiles; } if ( FilesInPath.Num() == 0 ) { UE_LOG(LogDerivedDataCacheCommandlet, Warning, TEXT("No files found.")); } ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms(); for (int32 Index = 0; Index < Platforms.Num(); Index++) { TArray<FName> DesiredShaderFormats; Platforms[Index]->GetShaderFormats(DesiredShaderFormats); for (int32 FormatIndex = 0; FormatIndex < DesiredShaderFormats.Num(); FormatIndex++) { const EShaderPlatform TargetPlatform = ShaderFormatToLegacyShaderPlatform(DesiredShaderFormats[FormatIndex]); // Kick off global shader compiles for each target platform GetGlobalShaderMap(TargetPlatform); } } const int32 GCInterval = 100; int32 NumProcessedSinceLastGC = GCInterval; bool bLastPackageWasMap = true; // 'true' is to prime the ProcessedPackages list TSet<FString> ProcessedPackages; UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("%d packages to load..."), FilesInPath.Num()); for( int32 FileIndex = FilesInPath.Num() - 1; ; FileIndex-- ) { // Keep track of which packages have already been processed along with the map. if (NumProcessedSinceLastGC >= GCInterval || bLastPackageWasMap || FileIndex == FilesInPath.Num() - 1) { const double FindProcessedPackagesStartTime = FPlatformTime::Seconds(); TArray<UObject *> ObjectsInOuter; GetObjectsWithOuter(NULL, ObjectsInOuter, false); for( int32 Index = 0; Index < ObjectsInOuter.Num(); Index++ ) { UPackage* Pkg = Cast<UPackage>(ObjectsInOuter[Index]); if (!Pkg) { continue; } FString Filename; if (FPackageName::DoesPackageExist(Pkg->GetName(), NULL, &Filename)) { if (!ProcessedPackages.Contains(Filename)) { ProcessedPackages.Add(Filename); PackagesToNotReload.Add(Pkg->GetName()); Pkg->PackageFlags |= PKG_ReloadingForCooker; { TArray<UObject *> ObjectsInPackage; GetObjectsWithOuter(Pkg, ObjectsInPackage, true); for( int32 IndexPackage = 0; IndexPackage < ObjectsInPackage.Num(); IndexPackage++ ) { ObjectsInPackage[IndexPackage]->CookerWillNeverCookAgain(); } } } } } FindProcessedPackagesTime += FPlatformTime::Seconds() - FindProcessedPackagesStartTime; } if (NumProcessedSinceLastGC >= GCInterval || FileIndex < 0 || bLastPackageWasMap) { const double StartGCTime = FPlatformTime::Seconds(); if (NumProcessedSinceLastGC >= GCInterval || FileIndex < 0) { UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("GC (Full)...")); CollectGarbage( RF_Native ); NumProcessedSinceLastGC = 0; } else { UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("GC...")); CollectGarbage( RF_Native | RF_Standalone ); } GCTime += FPlatformTime::Seconds() - StartGCTime; bLastPackageWasMap = false; } if (FileIndex < 0) { break; } const FString& Filename = FilesInPath[FileIndex]; if (ProcessedPackages.Contains(Filename)) { continue; } if (bDoSubset) { const FString& PackageName = FPackageName::PackageFromPath(*Filename); if (FCrc::StrCrc_DEPRECATED(*PackageName.ToUpper()) % SubsetMod != SubsetTarget) { continue; } } UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("Loading (%d) %s"), FilesInPath.Num() - FileIndex, *Filename ); UPackage* Package = LoadPackage( NULL, *Filename, LOAD_None ); if( Package == NULL ) { UE_LOG(LogDerivedDataCacheCommandlet, Error, TEXT("Error loading %s!"), *Filename ); } else { bLastPackageWasMap = Package->ContainsMap(); NumProcessedSinceLastGC++; } } } IConsoleManager::Get().ProcessUserConsoleInput(TEXT("Tex.DerivedDataTimings"), *GWarn, NULL); UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("Waiting for shaders to finish.")); GShaderCompilingManager->FinishAllCompilation(); UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("Done waiting for shaders to finish.")); GetDerivedDataCacheRef().WaitForQuiescence(true); UE_LOG(LogDerivedDataCacheCommandlet, Display, TEXT("%.2lfs spent looking for processed packages, %.2lfs spent on GC."), FindProcessedPackagesTime, GCTime); return 0; }
int32 UGatherTextFromAssetsCommandlet::Main(const FString& Params) { // Parse command line. TArray<FString> Tokens; TArray<FString> Switches; TMap<FString, FString> ParamVals; UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals); //Set config file const FString* ParamVal = ParamVals.Find(FString(TEXT("Config"))); FString GatherTextConfigPath; if ( ParamVal ) { GatherTextConfigPath = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config specified.")); return -1; } //Set config section ParamVal = ParamVals.Find(FString(TEXT("Section"))); FString SectionName; if ( ParamVal ) { SectionName = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config section specified.")); return -1; } //Include paths TArray<FString> IncludePaths; GetConfigArray(*SectionName, TEXT("IncludePaths"), IncludePaths, GatherTextConfigPath); if (IncludePaths.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No include paths in section %s"), *SectionName); return -1; } //Exclude paths TArray<FString> ExcludePaths; GetConfigArray(*SectionName, TEXT("ExcludePaths"), ExcludePaths, GatherTextConfigPath); //package extensions TArray<FString> PackageExts; GetConfigArray(*SectionName, TEXT("PackageExtensions"), PackageExts, GatherTextConfigPath); if (PackageExts.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No package extensions specified in section %s, using defaults"), *SectionName); PackageExts.Add(FString("*") + FPackageName::GetAssetPackageExtension()); PackageExts.Add(FString("*") + FPackageName::GetMapPackageExtension()); } //asset class exclude TArray<FString> ExcludeClasses; GetConfigArray(*SectionName, TEXT("ExcludeClasses"), ExcludeClasses, GatherTextConfigPath); FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); AssetRegistryModule.Get().SearchAllAssets( true ); FARFilter Filter; for(int32 i = 0; i < ExcludeClasses.Num(); i++) { UClass* FilterClass = FindObject<UClass>(ANY_PACKAGE, *ExcludeClasses[i]); if(FilterClass) { Filter.ClassNames.Add( FilterClass->GetFName() ); } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Invalid exclude class %s"), *ExcludeClasses[i]); } } TArray<FAssetData> AssetData; AssetRegistryModule.Get().GetAssets(Filter, AssetData); FString UAssetPackageExtension = FPackageName::GetAssetPackageExtension(); TSet< FString > LongPackageNamesToExclude; for (int Index = 0; Index < AssetData.Num(); Index++) { LongPackageNamesToExclude.Add( FPackageName::LongPackageNameToFilename( AssetData[Index].PackageName.ToString(), UAssetPackageExtension ) ); } //Get whether we should fix broken properties that we find. GetConfigBool(*SectionName, TEXT("bFixBroken"), bFixBroken, GatherTextConfigPath); // Add any manifest dependencies if they were provided TArray<FString> ManifestDependenciesList; GetConfigArray(*SectionName, TEXT("ManifestDependencies"), ManifestDependenciesList, GatherTextConfigPath); if( !ManifestInfo->AddManifestDependencies( ManifestDependenciesList ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("The GatherTextFromAssets commandlet couldn't find all the specified manifest dependencies.")); return -1; } //The main array of files to work from. TArray< FString > PackageFileNamesToLoad; TSet< FString > LongPackageNamesToProcess; TArray<FString> PackageFilesNotInIncludePath; TArray<FString> PackageFilesInExcludePath; TArray<FString> PackageFilesExcludedByClass; //Fill the list of packages to work from. uint8 PackageFilter = NORMALIZE_DefaultFlags; TArray<FString> Unused; for ( int32 PackageFilenameWildcardIdx = 0; PackageFilenameWildcardIdx < PackageExts.Num(); PackageFilenameWildcardIdx++ ) { const bool IsAssetPackage = PackageExts[PackageFilenameWildcardIdx] == ( FString( TEXT("*") )+ FPackageName::GetAssetPackageExtension() ); TArray<FString> PackageFiles; if ( !NormalizePackageNames( Unused, PackageFiles, PackageExts[PackageFilenameWildcardIdx], PackageFilter) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("No packages found with extension %i: '%s'"), PackageFilenameWildcardIdx, *PackageExts[PackageFilenameWildcardIdx]); continue; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("Found %i packages with extension %i: '%s'"), PackageFiles.Num(), PackageFilenameWildcardIdx, *PackageExts[PackageFilenameWildcardIdx]); } //Run through all the files found and add any that pass the include, exclude and filter constraints to OrderedPackageFilesToLoad for( int32 PackageFileIdx=0; PackageFileIdx<PackageFiles.Num(); ++PackageFileIdx ) { bool bExclude = false; //Ensure it matches the include paths if there are some. for( int32 IncludePathIdx=0; IncludePathIdx<IncludePaths.Num() ; ++IncludePathIdx ) { bExclude = true; if( PackageFiles[PackageFileIdx].MatchesWildcard(IncludePaths[IncludePathIdx]) ) { bExclude = false; break; } } if ( bExclude ) { PackageFilesNotInIncludePath.Add(PackageFiles[PackageFileIdx]); } //Ensure it does not match the exclude paths if there are some. for( int32 ExcludePathIdx=0; !bExclude && ExcludePathIdx<ExcludePaths.Num() ; ++ExcludePathIdx ) { if( PackageFiles[PackageFileIdx].MatchesWildcard(ExcludePaths[ExcludePathIdx]) ) { bExclude = true; PackageFilesInExcludePath.Add(PackageFiles[PackageFileIdx]); break; } } //Check that this is not on the list of packages that we don't care about e.g. textures. if ( !bExclude && IsAssetPackage && LongPackageNamesToExclude.Contains( PackageFiles[PackageFileIdx] ) ) { bExclude = true; PackageFilesExcludedByClass.Add(PackageFiles[PackageFileIdx]); } //If we haven't failed one of the above checks, add it to the array of packages to process. if(!bExclude) { TScopedPointer< FArchive > FileReader( IFileManager::Get().CreateFileReader( *PackageFiles[PackageFileIdx] ) ); if( FileReader ) { // Read package file summary from the file FPackageFileSummary PackageSummary; (*FileReader) << PackageSummary; // Early out check if the package has been flagged as needing localization gathering if( PackageSummary.PackageFlags & PKG_RequiresLocalizationGather || PackageSummary.GetFileVersionUE4() < VER_UE4_PACKAGE_REQUIRES_LOCALIZATION_GATHER_FLAGGING ) { PackageFileNamesToLoad.Add( PackageFiles[PackageFileIdx] ); } } } } } if ( PackageFileNamesToLoad.Num() == 0 ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No files found. Or none passed the include/exclude criteria.")); } CollectGarbage( RF_Native ); //Now go through the remaining packages in the main array and process them in batches. int32 PackagesPerBatchCount = 100; TArray< UPackage* > LoadedPackages; TArray< FString > LoadedPackageFileNames; TArray< FString > FailedPackageFileNames; TArray< UPackage* > PackagesToProcess; const int32 PackageCount = PackageFileNamesToLoad.Num(); const int32 BatchCount = PackageCount / PackagesPerBatchCount + (PackageCount % PackagesPerBatchCount > 0 ? 1 : 0); // Add an extra batch for any remainder if necessary if(PackageCount > 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loading %i packages in %i batches of %i."), PackageCount, BatchCount, PackagesPerBatchCount); } //Load the packages in batches int32 PackageIndex = 0; for( int32 BatchIndex = 0; BatchIndex < BatchCount; ++BatchIndex ) { int32 PackagesInThisBatch = 0; for( PackageIndex; PackageIndex < PackageCount && PackagesInThisBatch < PackagesPerBatchCount; ++PackageIndex ) { FString PackageFileName = PackageFileNamesToLoad[PackageIndex]; UPackage *Package = LoadPackage( NULL, *PackageFileName, LOAD_None ); if( Package ) { LoadedPackages.Add(Package); LoadedPackageFileNames.Add(PackageFileName); // Because packages may not have been resaved after this flagging was implemented, we may have added packages to load that weren't flagged - potential false positives. // The loading process should have reflagged said packages so that only true positives will have this flag. if( Package->RequiresLocalizationGather() ) { PackagesToProcess.Add( Package ); } } else { FailedPackageFileNames.Add( PackageFileName ); continue; } ++PackagesInThisBatch; } UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loaded %i packages in batch %i of %i."), PackagesInThisBatch, BatchIndex + 1, BatchCount); ProcessPackages(PackagesToProcess); PackagesToProcess.Empty(PackagesPerBatchCount); if( bFixBroken ) { for( int32 LoadedPackageIndex=0; LoadedPackageIndex < LoadedPackages.Num() ; ++LoadedPackageIndex ) { UPackage *Package = LoadedPackages[LoadedPackageIndex]; const FString PackageName = LoadedPackageFileNames[LoadedPackageIndex]; //Todo - link with source control. if( Package ) { if( Package->IsDirty() ) { if( SavePackageHelper( Package, *PackageName ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Saved Package %s."),*PackageName); } else { //TODO - Work out how to integrate with source control. The code from the source gatherer doesn't work. UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Could not save package %s. Probably due to source control. "),*PackageName); } } } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Failed to find one of the loaded packages.")); } } } CollectGarbage( RF_Native ); LoadedPackages.Empty(PackagesPerBatchCount); LoadedPackageFileNames.Empty(PackagesPerBatchCount); } for(auto i = ConflictTracker.Namespaces.CreateConstIterator(); i; ++i) { const FString& NamespaceName = i.Key(); const FConflictTracker::FKeyTable& KeyTable = i.Value(); for(auto j = KeyTable.CreateConstIterator(); j; ++j) { const FString& KeyName = j.Key(); const FConflictTracker::FEntryArray& EntryArray = j.Value(); for(int k = 0; k < EntryArray.Num(); ++k) { const FConflictTracker::FEntry& Entry = EntryArray[k]; switch(Entry.Status) { case EAssetTextGatherStatus::MissingKey: { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Detected missing key on asset \"%s\"."), *Entry.ObjectPath); } break; case EAssetTextGatherStatus::MissingKey_Resolved: { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Fixed missing key on asset \"%s\"."), *Entry.ObjectPath); } break; case EAssetTextGatherStatus::IdentityConflict: { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Detected duplicate identity with differing source on asset \"%s\"."), *Entry.ObjectPath); } break; case EAssetTextGatherStatus::IdentityConflict_Resolved: { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Fixed duplicate identity with differing source on asset \"%s\"."), *Entry.ObjectPath); } break; } } } } return 0; }
static STATUS ProcessArgs ( int Argc, char *Argv[] ) /*++ Routine Description: Process the command line arguments Arguments: As per standard C main() Returns: STATUS_SUCCESS - if successful STATUS_ERROR - otherwise --*/ { FILE_NAME_LIST *NewList; STATUS Status; Status = STATUS_SUCCESS; memset ((void *) &mGlobals, 0, sizeof (mGlobals)); // // Skip program name // Argc--; Argv++; if (Argc == 0) { Usage (); return STATUS_ERROR; } if (_stricmp (Argv[0], "-h") == 0 || _stricmp (Argv[0], "-?") == 0) { Usage (); return STATUS_ERROR; } // // Process until no more args. // while (Argc > 0) { if (_stricmp (Argv[0], "-rc") == 0) { Argc--; Argv++; if (Argc == 0) { Error (UTILITY_NAME, 0, 0, "mising HII resource file name", NULL); Status = STATUS_ERROR; goto Done; } strcpy (mGlobals.ResourceFileName, Argv[0]); mGlobals.Mode |= MODE_CREATE_HII_RESOURCE_FILE; } else if (_stricmp (Argv[0], "-hii") == 0) { Argc--; Argv++; if (Argc == 0) { Error (UTILITY_NAME, 0, 0, "mising HII package list file name", NULL); Status = STATUS_ERROR; goto Done; } strcpy (mGlobals.PackageListFileName, Argv[0]); mGlobals.Mode |= MODE_CREATE_HII_PACKAGE_LIST; } else if (_stricmp (Argv[0], "-g") == 0) { Argc--; Argv++; if (Argc == 0) { Error (UTILITY_NAME, 0, 0, "mising package list GUID", NULL); Status = STATUS_ERROR; goto Done; } Status = StringToGuid (Argv[0], &mGlobals.Guid); if (Status != STATUS_SUCCESS) { goto Done; } mGlobals.GuidSpecified = TRUE; } else { // // This is a package file // NewList = malloc (sizeof (FILE_NAME_LIST)); if (NewList == NULL) { Error (UTILITY_NAME, 0, 0, "memory allocation failure", NULL); Status = STATUS_ERROR; goto Done; } memset (NewList, 0, sizeof (FILE_NAME_LIST)); strcpy (NewList->FileName, Argv[0]); if (mGlobals.PackageFile == NULL) { mGlobals.PackageFile = NewList; } else { mGlobals.LastPackageFile->Next = NewList; } mGlobals.LastPackageFile = NewList; Status = LoadPackage (NewList); if (Status != STATUS_SUCCESS) { goto Done; } } Argc--; Argv++; } if (!mGlobals.GuidSpecified) { Error (UTILITY_NAME, 0, 0, "please specify HII pakcage list GUID", NULL); Status = STATUS_ERROR; } Done: if (Status != STATUS_SUCCESS) { FreeGlobals (); } return Status; }
void UWorld::LoadSecondaryLevels(bool bForce, TSet<FString>* CookedPackages) { check( GIsEditor ); // streamingServer // Only load secondary levels in the Editor, and not for commandlets. if( (!IsRunningCommandlet() || bForce) // Don't do any work for world info actors that are part of secondary levels being streamed in! && !IsAsyncLoading()) { for( int32 LevelIndex=0; LevelIndex<StreamingLevels.Num(); LevelIndex++ ) { ULevelStreaming* const StreamingLevel = StreamingLevels[LevelIndex]; if( StreamingLevel ) { bool bAlreadyCooked = false; // If we are cooking don't cook sub levels multiple times if they've already been cooked FString PackageFilename; const FString StreamingLevelWorldAssetPackageName = StreamingLevel->GetWorldAssetPackageName(); if (CookedPackages) { if (FPackageName::DoesPackageExist(StreamingLevelWorldAssetPackageName, NULL, &PackageFilename)) { PackageFilename = FPaths::ConvertRelativePathToFull(PackageFilename); bAlreadyCooked |= CookedPackages->Contains( PackageFilename ); } } bool bAlreadyLoaded = false; UPackage* LevelPackage = FindObject<UPackage>(NULL, *StreamingLevelWorldAssetPackageName,true); // don't need to do any extra work if the level is already loaded if ( LevelPackage && LevelPackage->IsFullyLoaded() ) { bAlreadyLoaded = true; } if ( !bAlreadyCooked && !bAlreadyLoaded ) { bool bLoadedLevelPackage = false; const FName StreamingLevelWorldAssetPackageFName = StreamingLevel->GetWorldAssetPackageFName(); // Load the package and find the world object. if( FPackageName::IsShortPackageName(StreamingLevelWorldAssetPackageFName) == false ) { ULevel::StreamedLevelsOwningWorld.Add(StreamingLevelWorldAssetPackageFName, this); LevelPackage = LoadPackage( NULL, *StreamingLevelWorldAssetPackageName, LOAD_None ); ULevel::StreamedLevelsOwningWorld.Remove(StreamingLevelWorldAssetPackageFName); if( LevelPackage ) { bLoadedLevelPackage = true; // Find the world object in the loaded package. UWorld* LoadedWorld = UWorld::FindWorldInPackage(LevelPackage); // If the world was not found, it could be a redirector to a world. If so, follow it to the destination world. if (!LoadedWorld) { LoadedWorld = UWorld::FollowWorldRedirectorInPackage(LevelPackage); } check(LoadedWorld); if ( !LevelPackage->IsFullyLoaded() ) { // LoadedWorld won't be serialized as there's a BeginLoad on the stack so we manually serialize it here. check( LoadedWorld->GetLinker() ); LoadedWorld->GetLinker()->Preload( LoadedWorld ); } // Keep reference to prevent garbage collection. check( LoadedWorld->PersistentLevel ); ULevel* NewLoadedLevel = LoadedWorld->PersistentLevel; NewLoadedLevel->OwningWorld = this; StreamingLevel->SetLoadedLevel(NewLoadedLevel); } } else { UE_LOG(LogSpawn, Warning, TEXT("Streaming level uses short package name (%s). Level will not be loaded."), *StreamingLevelWorldAssetPackageName); } // Remove this level object if the file couldn't be found. if ( !bLoadedLevelPackage ) { StreamingLevels.RemoveAt( LevelIndex-- ); MarkPackageDirty(); } } } } } }
FReply SPropertyEditorClass::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { TSharedPtr<FClassDragDropOp> ClassOperation = DragDropEvent.GetOperationAs<FClassDragDropOp>(); if (ClassOperation.IsValid()) { // We can only drop one item into the combo box, so drop the first one. FString AssetName = ClassOperation->ClassesToDrop[0]->GetName(); // Set the property, it will be verified as valid. SendToObjects(AssetName); return FReply::Handled(); } TSharedPtr<FUnloadedClassDragDropOp> UnloadedClassOp = DragDropEvent.GetOperationAs<FUnloadedClassDragDropOp>(); if (UnloadedClassOp.IsValid()) { // Check if the asset is loaded, used to see if the context menu should be available bool bAllAssetWereLoaded = true; TArray<FClassPackageData>& AssetArray = *(UnloadedClassOp->AssetsToDrop.Get()); // We can only drop one item into the combo box, so drop the first one. FString& AssetName = AssetArray[0].AssetName; // Check to see if the asset can be found, otherwise load it. UObject* Object = FindObject<UObject>(NULL, *AssetName); if(Object == NULL) { // Check to see if the dropped asset was a blueprint const FString& PackageName = AssetArray[0].GeneratedPackageName; Object = FindObject<UObject>(NULL, *FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName)); if(Object == NULL) { // Load the package. GWarn->BeginSlowTask(LOCTEXT("OnDrop_LoadPackage", "Fully Loading Package For Drop"), true, false); UPackage* Package = LoadPackage(NULL, *PackageName, LOAD_NoRedirects ); if(Package) { Package->FullyLoad(); } GWarn->EndSlowTask(); Object = FindObject<UObject>(Package, *AssetName); } if(Object->IsA(UBlueprint::StaticClass())) { // Get the default object from the generated class. Object = Cast<UBlueprint>(Object)->GeneratedClass->GetDefaultObject(); } } // Set the property, it will be verified as valid. SendToObjects(AssetName); return FReply::Handled(); } return FReply::Unhandled(); }
int32 UGenerateDistillFileSetsCommandlet::Main( const FString& InParams ) { // Parse command line. TArray<FString> Tokens; TArray<FString> Switches; UCommandlet::ParseCommandLine(*InParams, Tokens, Switches); TArray<FString> MapList; for ( int32 MapIdx = 0; MapIdx < Tokens.Num(); ++MapIdx ) { const FString& Map = Tokens[MapIdx]; if ( FPackageName::IsShortPackageName(Map) ) { FString LongPackageName; if ( FPackageName::SearchForPackageOnDisk(Map, &LongPackageName) ) { MapList.Add(LongPackageName); } else { UE_LOG(LogGenerateDistillFileSetsCommandlet, Error, TEXT("Unable to find package for map %s."), *Map); return 1; } } else { MapList.Add(Map); } } if ( MapList.Num() <= 0 ) { // No map tokens were supplied on the command line, so assume all maps TArray<FString> AllPackageFilenames; FEditorFileUtils::FindAllPackageFiles(AllPackageFilenames); for (int32 PackageIndex = 0; PackageIndex < AllPackageFilenames.Num(); PackageIndex++) { const FString& Filename = AllPackageFilenames[PackageIndex]; if (FPaths::GetExtension(Filename, true) == FPackageName::GetMapPackageExtension() ) { FString LongPackageName; if ( FPackageName::TryConvertFilenameToLongPackageName(Filename, LongPackageName) ) { // Warn about maps in "NoShip" or "TestMaps" folders. Those should have been filtered out during the Distill process! if( !Filename.Contains( "/NoShip/") && !Filename.Contains( "/TestMaps/")) { // @todo plugins add support for plugins? if ( LongPackageName.StartsWith(TEXT("/Game")) ) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT( "Discovered map package %s..." ), *LongPackageName ); MapList.Add(LongPackageName); } } else { UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT("Skipping map package %s in TestMaps or NoShip folder"), *Filename); } } else { UE_LOG(LogGenerateDistillFileSetsCommandlet, Warning, TEXT("Failed to determine package name for map file %s."), *Filename); } } } } const FString TemplateFileSwitch = TEXT("Template="); const FString OutputFileSwitch = TEXT("Output="); const FString TemplateFolderSwitch = TEXT("TemplateFolder="); const FString OutputFolderSwitch = TEXT("OutputFolder="); FString TemplateFilename; FString OutputFilename; FString TemplateFolder; FString OutputFolder; for (int32 SwitchIdx = 0; SwitchIdx < Switches.Num(); ++SwitchIdx) { const FString& Switch = Switches[SwitchIdx]; if ( Switch.StartsWith(TemplateFileSwitch) ) { Switch.Split(TEXT("="), NULL, &TemplateFilename); TemplateFilename = TemplateFilename.TrimQuotes(); } else if ( Switch.StartsWith(OutputFileSwitch) ) { Switch.Split(TEXT("="), NULL, &OutputFilename); OutputFilename = OutputFilename.TrimQuotes(); } else if ( Switch.StartsWith(TemplateFolderSwitch) ) { Switch.Split(TEXT("="), NULL, &TemplateFolder); TemplateFolder = TemplateFolder.TrimQuotes(); FPaths::NormalizeFilename(TemplateFolder); if ( !TemplateFolder.EndsWith(TEXT("/")) ) { TemplateFolder += TEXT("/"); } UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT("Using template folder: "), *TemplateFolder); } else if ( Switch.StartsWith(OutputFolderSwitch) ) { Switch.Split(TEXT("="), NULL, &OutputFolder); OutputFolder = OutputFolder.TrimQuotes(); FPaths::NormalizeFilename(OutputFolder); if ( !OutputFolder.EndsWith(TEXT("/")) ) { OutputFolder += TEXT("/"); } UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT("Using output folder: "), *OutputFolder); } } if ( OutputFilename.IsEmpty() ) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Error, TEXT("You must supply -Output=OutputFilename. These files are relative to the Game/Build directory.")); return 1; } if (OutputFolder.IsEmpty()) { OutputFolder = FPaths::GameDir() + TEXT("Build/"); } OutputFilename = OutputFolder + OutputFilename; bool bSimpleTxtOutput = false; // Load the template file FString TemplateFileContents; if (TemplateFilename.IsEmpty()) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Log, TEXT("No template specified, assuming a simple txt output.")); bSimpleTxtOutput = true; } // If no folder was specified, filenames are relative to the build dir. else { if (TemplateFolder.IsEmpty()) { TemplateFolder = FPaths::GameDir() + TEXT("Build/"); } TemplateFilename = TemplateFolder + TemplateFilename; if (!FFileHelper::LoadFileToString(TemplateFileContents, *TemplateFilename)) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Error, TEXT("Failed to load template file '%s'"), *TemplateFilename); return 1; } } // Form a full unique package list TSet<FString> AllPackageNames; //@todo SLATE: This is a hack to ensure all slate referenced assets get cooked. // Slate needs to be refactored to properly identify required assets at cook time. // Simply jamming everything in a given directory into the cook list is error-prone // on many levels - assets not required getting cooked/shipped; assets not put under // the correct folder; etc. { TArray<FString> UIContentPaths; if (GConfig->GetArray(TEXT("UI"), TEXT("ContentDirectories"), UIContentPaths, GEditorIni) > 0) { for (int32 DirIdx = 0; DirIdx < UIContentPaths.Num(); DirIdx++) { FString ContentPath = FPackageName::LongPackageNameToFilename(UIContentPaths[DirIdx]); TArray<FString> Files; IFileManager::Get().FindFilesRecursive(Files, *ContentPath, *(FString(TEXT("*")) + FPackageName::GetAssetPackageExtension()), true, false); for (int32 Index = 0; Index < Files.Num(); Index++) { FString StdFile = Files[Index]; FPaths::MakeStandardFilename(StdFile); StdFile = FPackageName::FilenameToLongPackageName(StdFile); AllPackageNames.Add(StdFile); } } } } // Load all maps { for ( auto MapIt = MapList.CreateConstIterator(); MapIt; ++MapIt ) { const FString& MapPackage = *MapIt; UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT( "Loading %s..." ), *MapPackage ); UPackage* Package = LoadPackage( NULL, *MapPackage, LOAD_None ); if( Package != NULL ) { AllPackageNames.Add(Package->GetName()); UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT( "Finding content referenced by %s..." ), *MapPackage ); TArray<UObject *> ObjectsInOuter; GetObjectsWithOuter(NULL, ObjectsInOuter, false); for (int32 Index = 0; Index < ObjectsInOuter.Num(); Index++) { FString OtherName = ObjectsInOuter[Index]->GetOutermost()->GetName(); if (!AllPackageNames.Contains(OtherName)) { AllPackageNames.Add(OtherName); UE_LOG(LogGenerateDistillFileSetsCommandlet, Log, TEXT("Package: %s"), *OtherName); } } UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT( "Collecting garbage..." ) ); CollectGarbage(RF_NoFlags); } } } // Sort the results to make it easier to diff files. No necessary but useful sometimes. TArray<FString> SortedPackageNames = AllPackageNames.Array(); SortedPackageNames.Sort(); // For the list of FileSets to include in the distill FString AllFileSets; const FString FileSetPathRoot = TEXT("Content"); for (auto PackageIt = SortedPackageNames.CreateConstIterator(); PackageIt; ++PackageIt) { const FString& PackageName = *PackageIt; // @todo plugins add support for plugins? if ( PackageName.StartsWith(TEXT("/Game")) ) { const FString PathWithoutRoot( PackageName.Mid( 5 ) ); const FString FileSetPath = FileSetPathRoot + PathWithoutRoot; if (bSimpleTxtOutput) { FString ActualFile; if (FPackageName::DoesPackageExist(PackageName, NULL, &ActualFile)) { ActualFile = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*ActualFile); AllFileSets += FString::Printf(TEXT("%s") LINE_TERMINATOR, *ActualFile); UE_LOG(LogGenerateDistillFileSetsCommandlet, Log, TEXT("File: %s"), *ActualFile); } } else { AllFileSets += FString::Printf(TEXT("<FileSet Path=\"%s.*\" bIsRecursive=\"false\"/>") LINE_TERMINATOR, *FileSetPath); } } } // Write the output file FString OutputFileContents; if (bSimpleTxtOutput) { OutputFileContents = AllFileSets; } else { OutputFileContents = TemplateFileContents.Replace(TEXT("%INSTALLEDCONTENTFILESETS%"), *AllFileSets, ESearchCase::CaseSensitive); if (FApp::HasGameName()) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Display, TEXT("Replacing %%GAMENAME%% with (%s)..."), FApp::GetGameName()); OutputFileContents = OutputFileContents.Replace(TEXT("%GAMENAME%"), FApp::GetGameName(), ESearchCase::CaseSensitive); } else { UE_LOG(LogGenerateDistillFileSetsCommandlet, Warning, TEXT("Failed to replace %%GAMENAME%% since we are running without a game name.")); } } if ( !FFileHelper::SaveStringToFile(OutputFileContents, *OutputFilename) ) { UE_LOG(LogGenerateDistillFileSetsCommandlet, Error, TEXT("Failed to save output file '%s'"), *OutputFilename); return 1; } return 0; }
UObject * UPackageMap::GetObjectFromNetGUID( FNetworkGUID NetGUID ) { if ( !ensure( NetGUID.IsValid() ) ) { return NULL; } if ( !ensure( !NetGUID.IsDefault() ) ) { return NULL; } FNetGuidCacheObject * CacheObjectPtr = Cache->ObjectLookup.Find( NetGUID ); if ( CacheObjectPtr == NULL ) { // We don't have the object mapped yet return NULL; } UObject * Object = CacheObjectPtr->Object.Get(); if ( Object != NULL ) { check( Object->GetPathName() == CacheObjectPtr->FullPath ); return Object; } if ( CacheObjectPtr->FullPath.IsEmpty() ) { // This probably isn't possible, but making it a warning UE_LOG( LogNetPackageMap, Warning, TEXT( "GetObjectFromNetGUID: No full path for %s" ), *NetGUID.ToString() ); return NULL; } if ( NetGUID.IsDynamic() ) { // Dynamic objects don't have stable names, so we can't possibly reload the same object UE_LOG( LogNetPackageMap, VeryVerbose, TEXT( "GetObjectFromNetGUID: Cannot re-create dynamic object after GC <%s, %s>" ), *NetGUID.ToString(), *CacheObjectPtr->FullPath ); return NULL; } // // The object was previously mapped, but we GC'd it // We need to reload it now // Object = StaticFindObject( UObject::StaticClass(), NULL, *CacheObjectPtr->FullPath, false ); if ( Object == NULL ) { if ( IsNetGUIDAuthority() ) { // The authority shouldn't be loading resources on demand, at least for now. // This could be garbage or a security risk // Another possibility is in dynamic property replication if the server reads the previously serialized state // that has a now destroyed actor in it. UE_LOG( LogNetPackageMap, Warning, TEXT( "GetObjectFromNetGUID: Could not find Object for: NetGUID <%s, %s> (and IsNetGUIDAuthority())" ), *NetGUID.ToString(), *CacheObjectPtr->FullPath ); return NULL; } else { UE_LOG( LogNetPackageMap, Log, TEXT( "GetObjectFromNetGUID: Could not find Object for: NetGUID <%s, %s>"), *NetGUID.ToString(), *CacheObjectPtr->FullPath ); } Object = StaticLoadObject( UObject::StaticClass(), NULL, *CacheObjectPtr->FullPath, NULL, LOAD_NoWarn ); if ( Object ) { UE_LOG( LogNetPackageMap, Log, TEXT( "GetObjectFromNetGUID: StaticLoadObject. Found: %s" ), Object ? *Object->GetName() : TEXT( "NULL" ) ); } else { Object = LoadPackage( NULL, *CacheObjectPtr->FullPath, LOAD_None ); UE_LOG( LogNetPackageMap, Log, TEXT( "GetObjectFromNetGUID: LoadPackage. Found: %s" ), Object ? *Object->GetName() : TEXT( "NULL" ) ); } } else { // If we actually found the object, we probably shouldn't have GC'd it, so that's odd UE_LOG( LogNetPackageMap, Warning, TEXT( "GetObjectFromNetGUID: Object should not be found after GC: <%s, %s>" ), *NetGUID.ToString(), *CacheObjectPtr->FullPath ); } if ( Object == NULL ) { // If we get here, that means we have an invalid path, which shouldn't be possible, but making it a warning UE_LOG( LogNetPackageMap, Warning, TEXT( "GetObjectFromNetGUID: FAILED to re-create object after GC: <%s, %s>" ), *NetGUID.ToString(), *CacheObjectPtr->FullPath ); } else { // Reassign the object pointer for quick access next time CacheObjectPtr->Object = Object; // Make sure the object is in the GUIDToObjectLookup. Cache->NetGUIDLookup.Add( Object, NetGUID ); } return Object; }
int32 UFixupRedirectsCommandlet::Main( const FString& Params ) { // Retrieve list of all packages in .ini paths. TArray<FString> PackageList; FEditorFileUtils::FindAllPackageFiles(PackageList); if( !PackageList.Num() ) { return 0; } // process the commandline FString Token; const TCHAR* CommandLine = *Params; bool bIsQuietMode = false; bool bIsTestOnly = false; bool bShouldRestoreProgress= false; bool bIsSCCDisabled = false; bool bUpdateEnginePackages = false; bool bDeleteRedirects = true; bool bDeleteOnlyReferencedRedirects = false; bool bAutoSubmit = false; bool bSandboxed = IFileManager::Get().IsSandboxEnabled(); while (FParse::Token(CommandLine, Token, 1)) { if (Token == TEXT("-nowarn")) { bIsQuietMode = true; } else if (Token == TEXT("-testonly")) { bIsTestOnly = true; } else if (Token == TEXT("-restore")) { bShouldRestoreProgress = true; } else if (Token == TEXT("-NoAutoCheckout")) { bIsSCCDisabled = true; } else if (Token == TEXT("-AutoSubmit")) { bAutoSubmit = true; } else if (Token == TEXT("-UpdateEnginePackages")) { bUpdateEnginePackages = true; } else if (Token == TEXT("-NoDelete")) { bDeleteRedirects = false; } else if (Token == TEXT("-NoDeleteUnreferenced")) { bDeleteOnlyReferencedRedirects = true; } else if ( Token.Left(1) != TEXT("-") ) { FPackageName::SearchForPackageOnDisk(Token, &GRedirectCollector.FileToFixup); } } if (bSandboxed) { UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Running in a sandbox.")); bIsSCCDisabled = true; bAutoSubmit = false; bDeleteRedirects = false; } bool bShouldSkipErrors = false; // Setup file Output log in the Saved Directory const FString ProjectDir = FPaths::GetPath(FPaths::GetProjectFilePath()); const FString LogFilename = FPaths::Combine(*ProjectDir, TEXT("Saved"), TEXT("FixupRedirect"), TEXT("FixupRedirect.log")); FArchive* LogOutputFile = IFileManager::Get().CreateFileWriter(*LogFilename); LogOutputFile->Logf(TEXT("[Redirects]")); ///////////////////////////////////////////////////////////////////// // Display any script code referenced redirects ///////////////////////////////////////////////////////////////////// TArray<FString> UpdatePackages; TArray<FString> RedirectorsThatCantBeCleaned; if (!bShouldRestoreProgress) { // load all string asset reference targets, and add fake redirectors for them GRedirectCollector.ResolveStringAssetReference(); for (int32 RedirIndex = 0; RedirIndex < GRedirectCollector.Redirections.Num(); RedirIndex++) { FRedirection& Redir = GRedirectCollector.Redirections[RedirIndex]; UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Boot redirector can't be cleaned: %s(%s) -> %s(%s)"), *Redir.RedirectorName, *Redir.RedirectorPackageFilename, *Redir.DestinationObjectName, *Redir.PackageFilename); RedirectorsThatCantBeCleaned.AddUnique(Redir.RedirectorName); } ///////////////////////////////////////////////////////////////////// // Build a list of packages that need to be updated ///////////////////////////////////////////////////////////////////// SET_WARN_COLOR(COLOR_WHITE); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Generating list of tasks:")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("-------------------------")); CLEAR_WARN_COLOR(); int32 GCIndex = 0; // process script code first pass, then everything else for( int32 PackageIndex = 0; PackageIndex < PackageList.Num(); PackageIndex++ ) { const FString& Filename = PackageList[PackageIndex]; // already loaded code, skip them, and skip autosave packages if (Filename.StartsWith(AutoSaveUtils::GetAutoSaveDir(), ESearchCase::IgnoreCase)) { continue; } UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Looking for redirects in %s..."), *Filename); // Assert if package couldn't be opened so we have no chance of messing up saving later packages. UPackage* Package = Cast<UPackage>(LoadPackage(NULL, *Filename, 0)); // load all string asset reference targets, and add fake redirectors for them GRedirectCollector.ResolveStringAssetReference(); if (!Package) { SET_WARN_COLOR(COLOR_RED); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... failed to open %s"), *Filename); CLEAR_WARN_COLOR(); // if we are not in quiet mode, and the user wants to continue, go on const FText Message = FText::Format( NSLOCTEXT("Unreal", "PackageFailedToOpen", "The package '{0}' failed to open. Should this commandlet continue operation, ignoring further load errors? Continuing may have adverse effects (object references may be lost)."), FText::FromString( Filename ) ); if (bShouldSkipErrors || (!bIsQuietMode && GWarn->YesNof( Message ))) { bShouldSkipErrors = true; continue; } else { return 1; } } // all notices here about redirects get this color SET_WARN_COLOR(COLOR_DARK_GREEN); // look for any redirects that were followed that are referenced by this package // (may have been loaded earlier if this package was loaded by script code) // any redirectors referenced by script code can't be cleaned up for (int32 RedirIndex = 0; RedirIndex < GRedirectCollector.Redirections.Num(); RedirIndex++) { FRedirection& Redir = GRedirectCollector.Redirections[RedirIndex]; if (Redir.PackageFilename == Filename) { UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... references %s [-> %s]"), *Redir.RedirectorName, *Redir.DestinationObjectName); // put the source and dest packages in the list to be updated UpdatePackages.AddUnique(Redir.PackageFilename); UpdatePackages.AddUnique(Redir.RedirectorPackageFilename); } } // clear the flag for needing to collect garbage bool bNeedToCollectGarbage = false; // if this package has any redirectors, make sure we update it if (!GRedirectCollector.FileToFixup.Len() || GRedirectCollector.FileToFixup == FPackageName::FilenameToLongPackageName(Filename)) { TArray<UObject *> ObjectsInOuter; GetObjectsWithOuter(Package, ObjectsInOuter); for( int32 Index = 0; Index < ObjectsInOuter.Num(); Index++ ) { UObject* Obj = ObjectsInOuter[Index]; UObjectRedirector* Redir = Cast<UObjectRedirector>(Obj); if (Redir) { // make sure this package is in the list of packages to update UpdatePackages.AddUnique(Filename); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... has redirect %s [-> %s]"), *Redir->GetPathName(), *Redir->DestinationObject->GetFullName()); LogOutputFile->Logf(TEXT("%s = %s"), *Redir->GetPathName(), *Redir->DestinationObject->GetFullName()); // make sure we GC if we found a redirector bNeedToCollectGarbage = true; } } } CLEAR_WARN_COLOR(); // collect garbage every N packages, or if there was any redirectors in the package // (to make sure that redirectors get reloaded properly and followed by the callback) // also, GC after loading a map package, to make sure it's unloaded so that we can track // other packages loading a map package as a dependency if (((++GCIndex) % 50) == 0 || bNeedToCollectGarbage || Package->ContainsMap()) { // collect garbage to close the package CollectGarbage(RF_Native); UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("GC...")); // reset our counter GCIndex = 0; } } // save off restore point FArchive* Ar = IFileManager::Get().CreateFileWriter(*(FPaths::GameSavedDir() + TEXT("Fixup.bin"))); *Ar << GRedirectCollector.Redirections; *Ar << UpdatePackages; *Ar << RedirectorsThatCantBeCleaned; delete Ar; } else { // load restore point FArchive* Ar = IFileManager::Get().CreateFileReader(*(FPaths::GameSavedDir() + TEXT("Fixup.bin"))); if( Ar != NULL ) { *Ar << GRedirectCollector.Redirections; *Ar << UpdatePackages; *Ar << RedirectorsThatCantBeCleaned; delete Ar; } } // unregister the callback so we stop getting redirections added FCoreUObjectDelegates::RedirectorFollowed.RemoveAll(&GRedirectCollector); ///////////////////////////////////////////////////////////////////// // Explain to user what is happening ///////////////////////////////////////////////////////////////////// SET_WARN_COLOR(COLOR_YELLOW); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Files that need to fixed up:")); SET_WARN_COLOR(COLOR_DARK_YELLOW); // print out the working set of packages for (int32 PackageIndex = 0; PackageIndex < UpdatePackages.Num(); PackageIndex++) { UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" %s"), *UpdatePackages[PackageIndex]); } UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); CLEAR_WARN_COLOR(); // if we are only testing, just just quiet before actually doing anything if (bIsTestOnly) { LogOutputFile->Close(); delete LogOutputFile; LogOutputFile = NULL; return 0; } ///////////////////////////////////////////////////////////////////// // Find redirectors that are referenced by packages we cant check out ///////////////////////////////////////////////////////////////////// bool bEngineRedirectorCantBeCleaned = false; ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); // initialize source control if it hasn't been initialized yet if(!bIsSCCDisabled) { SourceControlProvider.Init(); //Make sure we can check out all packages - update their state first SourceControlProvider.Execute(ISourceControlOperation::Create<FUpdateStatus>(), UpdatePackages); } for( int32 PackageIndex = 0; PackageIndex < UpdatePackages.Num(); PackageIndex++ ) { const FString& Filename = UpdatePackages[PackageIndex]; bool bCanEdit = true; if(!bIsSCCDisabled) { FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(Filename, EStateCacheUsage::ForceUpdate); if(SourceControlState.IsValid() && !SourceControlState->CanEdit()) { bCanEdit = false; } } else if(IFileManager::Get().IsReadOnly(*Filename)) { bCanEdit = false; } if(!bCanEdit) { const bool bAllowCheckout = bUpdateEnginePackages || !Filename.StartsWith( FPaths::EngineDir() ); if (!bIsSCCDisabled && bAllowCheckout) { FString PackageName(FPackageName::FilenameToLongPackageName(Filename)); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(Filename, EStateCacheUsage::ForceUpdate); if (SourceControlState.IsValid() && SourceControlState->CanCheckout()) { SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), SourceControlHelpers::PackageFilename(PackageName)); FSourceControlStatePtr NewSourceControlState = SourceControlProvider.GetState(Filename, EStateCacheUsage::ForceUpdate); bCanEdit = NewSourceControlState.IsValid() && NewSourceControlState->CanEdit(); } } // if the checkout failed for any reason, we can't clean it up if (bAllowCheckout && !bCanEdit) { SET_WARN_COLOR(COLOR_RED); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Couldn't check out/edit %s..."), *Filename); CLEAR_WARN_COLOR(); // load all string asset reference targets, and add fake redirectors for them GRedirectCollector.ResolveStringAssetReference(); // any redirectors that are pointed to by this read-only package can't be fixed up for (int32 RedirIndex = 0; RedirIndex < GRedirectCollector.Redirections.Num(); RedirIndex++) { FRedirection& Redir = GRedirectCollector.Redirections[RedirIndex]; // any redirectors pointed to by this file we don't clean if (Redir.PackageFilename == Filename) { RedirectorsThatCantBeCleaned.AddUnique(Redir.RedirectorName); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... can't fixup references to %s"), *Redir.RedirectorName); // if this redirector is in an Engine package, we need to alert the user, because // Engine packages are shared between games, so if one game still needs the redirector // to be valid, then we can't check in Engine packages after another game has // run that could if (!bEngineRedirectorCantBeCleaned) { FString PackagePath; FPackageName::DoesPackageExist(Redir.RedirectorPackageFilename, NULL, &PackagePath); if (PackagePath.StartsWith(FPaths::EngineDir())) { bEngineRedirectorCantBeCleaned = true; } } } // any redirectors in this file can't be deleted else if (Redir.RedirectorPackageFilename == Filename) { RedirectorsThatCantBeCleaned.AddUnique(Redir.RedirectorName); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... can't delete %s"), *Redir.RedirectorName); } } } else { SET_WARN_COLOR(COLOR_DARK_GREEN); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Checked out %s..."), *Filename); CLEAR_WARN_COLOR(); } } } // warn about an engine package that can't be cleaned up (may want to revert engine packages) if (bEngineRedirectorCantBeCleaned) { UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Engine package redirectors are referenced by packages that can't be cleaned. If you have multiple games, it's recommended you revert any checked out Engine packages.")); bUpdateEnginePackages=false; } UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); ///////////////////////////////////////////////////////////////////// // Load and save packages to save out the proper fixed up references ///////////////////////////////////////////////////////////////////// SET_WARN_COLOR(COLOR_WHITE); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Fixing references to point to proper objects:")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("---------------------------------------------")); CLEAR_WARN_COLOR(); // keep a list of all packages that have ObjectRedirects in them. This is not needed if we aren't deleting redirects TArray<bool> PackagesWithRedirects; // Delete these packages entirely because they are empty TArray<bool> EmptyPackagesToDelete; if ( bDeleteRedirects ) { PackagesWithRedirects.AddZeroed(UpdatePackages.Num()); EmptyPackagesToDelete.AddZeroed(PackageList.Num()); } bool bSCCEnabled = ISourceControlModule::Get().IsEnabled(); // Iterate over all packages, loading and saving to remove all references to ObjectRedirectors (can't delete the Redirects yet) for( int32 PackageIndex = 0; PackageIndex < UpdatePackages.Num(); PackageIndex++ ) { const FString& Filename = UpdatePackages[PackageIndex]; // we can't do anything with packages that are read-only or cant be edited due to source control (we don't want to fixup the redirects) if(bSCCEnabled) { FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(SourceControlHelpers::PackageFilename(Filename), EStateCacheUsage::ForceUpdate); if(SourceControlState.IsValid() && !SourceControlState->CanEdit()) { continue; } } else if(IFileManager::Get().IsReadOnly(*Filename)) { continue; } // Assert if package couldn't be opened so we have no chance of messing up saving later packages. UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Cleaning %s"), *Filename); UPackage* Package = LoadPackage( NULL, *Filename, LOAD_NoVerify ); // load all string asset reference targets, and add fake redirectors for them GRedirectCollector.ResolveStringAssetReference(); // if it failed to open, we have already dealt with quitting if we are going to, so just skip it if (!Package) { continue; } if ( bDeleteOnlyReferencedRedirects && bDeleteRedirects ) { TArray<UObject *> ObjectsInOuter; GetObjectsWithOuter(Package, ObjectsInOuter); for( int32 Index = 0; Index < ObjectsInOuter.Num(); Index++ ) { UObject* Obj = ObjectsInOuter[Index]; UObjectRedirector* Redir = Cast<UObjectRedirector>(Obj); if (Redir) { PackagesWithRedirects[PackageIndex] = 1; break; } } } // Don't save packages in the engine directory if we did not opt to update engine packages if( bUpdateEnginePackages || !Filename.StartsWith( FPaths::EngineDir() ) ) { // save out the package UWorld* World = UWorld::FindWorldInPackage(Package); GEditor->SavePackage( Package, World, World ? RF_NoFlags : RF_Standalone, *Filename, GWarn ); } // collect garbage to close the package UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Collecting Garbage...")); CollectGarbage(RF_Native); } UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); if ( bDeleteRedirects ) { ///////////////////////////////////////////////////////////////////// // Delete all redirects that are no longer referenced ///////////////////////////////////////////////////////////////////// SET_WARN_COLOR(COLOR_WHITE); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Deleting redirector objects:")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("----------------------------")); CLEAR_WARN_COLOR(); const TArray<FString>& PackagesToCleaseOfRedirects = bDeleteOnlyReferencedRedirects ? UpdatePackages : PackageList; int32 GCIndex = 0; // Again, iterate over all packages, loading and saving to and this time deleting all for( int32 PackageIndex = 0; PackageIndex < PackagesToCleaseOfRedirects.Num(); PackageIndex++ ) { const FString& Filename = PackagesToCleaseOfRedirects[PackageIndex]; if (bDeleteOnlyReferencedRedirects && PackagesWithRedirects[PackageIndex] == 0) { continue; } // The file should have already been checked out/be writable // If it is read only that means the checkout failed or we are not using source control and we can not write this file. if(bSCCEnabled) { FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(SourceControlHelpers::PackageFilename(Filename), EStateCacheUsage::ForceUpdate); if(SourceControlState.IsValid() && !SourceControlState->CanEdit()) { UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Skipping file: source control says we cant edit the file %s..."), *Filename); continue; } } else if( IFileManager::Get().IsReadOnly( *Filename )) { UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Skipping read-only file %s..."), *Filename); continue; } UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Wiping %s..."), *Filename); UPackage* Package = LoadPackage( NULL, *Filename, 0 ); // load all string asset reference targets, and add fake redirectors for them GRedirectCollector.ResolveStringAssetReference(); // if it failed to open, we have already dealt with quitting if we are going to, so just skip it if (!Package) { continue; } // assume that all redirs in this file are still-referenced bool bIsDirty = false; // see if this package is completely empty other than purged redirectors and metadata bool bIsEmpty = true; // delete all ObjectRedirects now TArray<UObjectRedirector*> Redirs; // find all redirectors, put into an array so delete doesn't mess up the iterator TArray<UObject *> ObjectsInOuter; GetObjectsWithOuter(Package, ObjectsInOuter); for( int32 Index = 0; Index < ObjectsInOuter.Num(); Index++ ) { UObject* Obj = ObjectsInOuter[Index]; UObjectRedirector *Redir = Cast<UObjectRedirector>(Obj); if (Redir) { int32 Dummy; // if the redirector was marked as uncleanable, skip it if (RedirectorsThatCantBeCleaned.Find(Redir->GetFullName(), Dummy)) { SET_WARN_COLOR(COLOR_DARK_RED); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... skipping still-referenced %s"), *Redir->GetFullName()); CLEAR_WARN_COLOR(); bIsEmpty = false; continue; } bIsDirty = true; SET_WARN_COLOR(COLOR_DARK_GREEN); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... deleting %s"), *Redir->GetFullName()); CLEAR_WARN_COLOR(); Redirs.Add(Redir); } else if ( (!Obj->IsA(UMetaData::StaticClass()) && !Obj->IsA(UField::StaticClass())) || Obj->IsA(UUserDefinedEnum::StaticClass())) // UserDefinedEnum should not be deleted { // This package has a real object bIsEmpty = false; } } if (bIsEmpty && !bDeleteOnlyReferencedRedirects) { EmptyPackagesToDelete[PackageIndex] = 1; } // mark them for deletion. for (int32 RedirIndex = 0; RedirIndex < Redirs.Num(); RedirIndex++) { UObjectRedirector* Redirector = Redirs[RedirIndex]; // Remove standalone flag and mark as pending kill. Redirector->ClearFlags( RF_Standalone | RF_Public ); // We don't need redirectors in the root set, the references should already be fixed up if ( Redirector->IsRooted() ) { Redirector->RemoveFromRoot(); } Redirector->MarkPendingKill(); } Redirs.Empty(); if (bIsDirty) { // Don't save packages in the engine directory if we did not opt to update engine packages if( bUpdateEnginePackages || !Filename.StartsWith( FPaths::EngineDir() ) ) { // save the package UWorld* World = UWorld::FindWorldInPackage(Package); GEditor->SavePackage( Package, World, World ? RF_NoFlags : RF_Standalone, *Filename, GWarn ); } } // collect garbage every N packages, or if there was any redirectors in the package if (((++GCIndex) % 50) == 0 || bIsDirty || Package->ContainsMap()) { // collect garbage to close the package CollectGarbage(RF_Native); UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("GC...")); // reset our counter GCIndex = 0; } } UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); } else { SET_WARN_COLOR(COLOR_WHITE); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("----------------------------")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Not deleting any redirector objects:")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("----------------------------")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("")); CLEAR_WARN_COLOR(); } ///////////////////////////////////////////////////////////////////// // Clean up any unused trash ///////////////////////////////////////////////////////////////////// SET_WARN_COLOR(COLOR_WHITE); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Deleting empty and unused packages:")); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("---------------------------------------")); CLEAR_WARN_COLOR(); LogOutputFile->Logf(TEXT("")); LogOutputFile->Logf(TEXT("[Deleted]")); // Iterate over packages, attempting to delete unreferenced packages for( int32 PackageIndex = 0; PackageIndex < PackageList.Num(); PackageIndex++ ) { bool bDelete = false; const FString& Filename = PackageList[PackageIndex]; FString PackageName(FPackageName::FilenameToLongPackageName(Filename)); const bool bAllowDelete = bUpdateEnginePackages || !Filename.StartsWith( FPaths::EngineDir() ); if (bDeleteRedirects && !bDeleteOnlyReferencedRedirects && EmptyPackagesToDelete[PackageIndex] && bAllowDelete) { // this package is completely empty, delete it bDelete = true; } if (bDelete == true) { struct Local { static bool DeleteFromDisk(const FString& InFilename, const FString& InMessage) { SET_WARN_COLOR(COLOR_GREEN); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("%s"), *InMessage); if (!IFileManager::Get().Delete(*InFilename, false, true)) { SET_WARN_COLOR(COLOR_RED); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT(" ... failed to delete from disk."), *InFilename); CLEAR_WARN_COLOR(); return false; } CLEAR_WARN_COLOR(); return true; } }; if (!bIsSCCDisabled) { // get file SCC status FString FileName = SourceControlHelpers::PackageFilename(PackageName); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(FileName, EStateCacheUsage::ForceUpdate); if(SourceControlState.IsValid() && (SourceControlState->IsCheckedOut() || SourceControlState->IsAdded()) ) { UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Revert '%s' from source control..."), *Filename); SourceControlProvider.Execute(ISourceControlOperation::Create<FRevert>(), FileName); SET_WARN_COLOR(COLOR_GREEN); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Deleting '%s' from source control..."), *Filename); CLEAR_WARN_COLOR(); SourceControlProvider.Execute(ISourceControlOperation::Create<FDelete>(), FileName); } else if(SourceControlState.IsValid() && SourceControlState->CanCheckout()) { SET_WARN_COLOR(COLOR_GREEN); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Deleting '%s' from source control..."), *Filename); CLEAR_WARN_COLOR(); SourceControlProvider.Execute(ISourceControlOperation::Create<FDelete>(), FileName); } else if(SourceControlState.IsValid() && SourceControlState->IsCheckedOutOther()) { SET_WARN_COLOR(COLOR_RED); UE_LOG(LogFixupRedirectsCommandlet, Warning, TEXT("Couldn't delete '%s' from source control, someone has it checked out, skipping..."), *Filename); CLEAR_WARN_COLOR(); } else if(SourceControlState.IsValid() && !SourceControlState->IsSourceControlled()) { if(Local::DeleteFromDisk(Filename, FString::Printf(TEXT("'%s' is not in source control, attempting to delete from disk..."), *Filename))) { LogOutputFile->Logf(*Filename); } } else { if(Local::DeleteFromDisk(Filename, FString::Printf(TEXT("'%s' is in an unknown source control state, attempting to delete from disk..."), *Filename))) { LogOutputFile->Logf(*Filename); } } } else { if(Local::DeleteFromDisk(Filename, FString::Printf(TEXT("source control disabled while deleting '%s', attempting to delete from disk..."), *Filename))) { LogOutputFile->Logf(*Filename); } } } } LogOutputFile->Close(); delete LogOutputFile; LogOutputFile = NULL; if (!bIsSCCDisabled && bAutoSubmit) { ///////////////////////////////////////////////////////////////////// // Submit the results to source control ///////////////////////////////////////////////////////////////////// UE_LOG(LogFixupRedirectsCommandlet, Display, TEXT("Submiting the results to source control")); // Work out the list of file to check in TArray <FString> FilesToSubmit; for( int32 PackageIndex = 0; PackageIndex < PackageList.Num(); PackageIndex++ ) { const FString& Filename = PackageList[PackageIndex]; FString PackageName(FPackageName::FilenameToLongPackageName(Filename)); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(SourceControlHelpers::PackageFilename(Filename), EStateCacheUsage::ForceUpdate); if( SourceControlState.IsValid() && (SourceControlState->IsCheckedOut() || SourceControlState->IsAdded() || SourceControlState->IsDeleted()) ) { // Only submit engine packages if we're requested to if( bUpdateEnginePackages || !Filename.StartsWith( FPaths::EngineDir() ) ) { FilesToSubmit.Add(*PackageName); } } } // Check in all changed files const FText Description = NSLOCTEXT("FixupRedirectsCmdlet", "ChangelistDescription", "Fixed up Redirects"); TSharedRef<FCheckIn, ESPMode::ThreadSafe> CheckInOperation = ISourceControlOperation::Create<FCheckIn>(); CheckInOperation->SetDescription( Description ); SourceControlProvider.Execute(CheckInOperation, SourceControlHelpers::PackageFilenames(FilesToSubmit)); // toss the SCC manager ISourceControlModule::Get().GetProvider().Close(); } return 0; }
bool EngineUtils::FindOrLoadAssetsByPath(const FString& Path, TArray<UObject*>& OutAssets) { if ( !FPackageName::IsValidLongPackageName(Path, true) ) { return false; } // Convert the package path to a filename with no extension (directory) const FString FilePath = FPackageName::LongPackageNameToFilename(Path); // Gather the package files in that directory and subdirectories TArray<FString> Filenames; FPackageName::FindPackagesInDirectory(Filenames, FilePath); // Cull out map files for (int32 FilenameIdx = Filenames.Num() - 1; FilenameIdx >= 0; --FilenameIdx) { const FString Extension = FPaths::GetExtension(Filenames[FilenameIdx], true); if ( Extension == FPackageName::GetMapPackageExtension() ) { Filenames.RemoveAt(FilenameIdx); } } // Load packages or find existing ones and fully load them TSet<UPackage*> Packages; for (int32 FileIdx = 0; FileIdx < Filenames.Num(); ++FileIdx) { const FString& Filename = Filenames[FileIdx]; UPackage* Package = FindPackage(NULL, *FPackageName::FilenameToLongPackageName(Filename)); if (Package) { Package->FullyLoad(); } else { Package = LoadPackage(NULL, *Filename, LOAD_None); } if (Package) { Packages.Add(Package); } } // If any packages were successfully loaded, find all assets that were in the packages and add them to OutAssets if ( Packages.Num() > 0 ) { for (FObjectIterator ObjIt; ObjIt; ++ObjIt) { if ( Packages.Contains(ObjIt->GetOutermost()) && ObjIt->IsAsset() ) { OutAssets.Add(*ObjIt); } } } return true; }