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;
}
示例#4
0
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);
	}
}
示例#7
0
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;
}
示例#8
0
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);
				}
			}
		}
	}
}
示例#9
0
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);
		}
	}
}
示例#10
0
/**
 * 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;
}
示例#14
0
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 );
	}
}
示例#15
0
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;
}
示例#20
0
文件: HiiPack.c 项目: Kohrara/edk
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;
}
示例#21
0
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;
}
示例#24
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;
}
示例#26
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;
}