bool FCollection::Save(FText& OutError) { if ( !ensure(SourceFilename.Len()) ) { OutError = LOCTEXT("Error_Internal", "There was an internal error."); return false; } // Store the start time for profiling reasons double SaveStartTime = FPlatformTime::Seconds(); // Keep track of save progress to update the slow task dialog const int32 SaveProgressDenominator = 3; int32 SaveProgressNumerator = 0; GWarn->BeginSlowTask( FText::Format( LOCTEXT("SavingCollection", "Saving Collection {0}"), FText::FromName( CollectionName ) ), true); GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bUseSCC ) { // Checkout the file if ( !CheckoutCollection(OutError) ) { UE_LOG(LogCollectionManager, Error, TEXT("Failed to check out a collection file: %s"), *CollectionName.ToString()); GWarn->EndSlowTask(); return false; } } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); // Generate a string with the file contents FString FileOutput; // Start with the header TMap<FString,FString> HeaderPairs; SaveHeaderPairs(HeaderPairs); for (const auto& HeaderPair : HeaderPairs) { FileOutput += HeaderPair.Key + TEXT(":") + HeaderPair.Value + LINE_TERMINATOR; } FileOutput += LINE_TERMINATOR; // Now for the content if ( IsDynamic() ) { // @todo Dynamic collections } else { // Write out the set as a sorted array to keep things in a known order for diffing TArray<FName> ObjectList = ObjectSet.Array(); ObjectList.Sort(); // Static collection. Save a flat list of all objects in the collection. for (const FName& ObjectName : ObjectList) { FileOutput += ObjectName.ToString() + LINE_TERMINATOR; } } // Attempt to save the file bool bSaveSuccessful = false; if ( ensure(FileOutput.Len()) ) { // We have some output, write it to file if ( FFileHelper::SaveStringToFile(FileOutput, *SourceFilename) ) { bSaveSuccessful = true; } else { OutError = FText::Format(LOCTEXT("Error_WriteFailed", "Failed to write to collection file: {0}"), FText::FromString(SourceFilename)); UE_LOG(LogCollectionManager, Error, TEXT("%s"), *OutError.ToString()); } } else { OutError = LOCTEXT("Error_Internal", "There was an internal error."); } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bSaveSuccessful ) { if ( bUseSCC ) { // Check in the file if the save was successful if ( bSaveSuccessful ) { if ( !CheckinCollection(OutError) ) { UE_LOG(LogCollectionManager, Error, TEXT("Failed to check in a collection successfully saving: %s"), *CollectionName.ToString()); bSaveSuccessful = false; } } // If the save was not successful or the checkin failed, revert if ( !bSaveSuccessful ) { FText Unused; if ( !RevertCollection(Unused) ) { // The revert failed... file will be left on disk as it was saved. // DiskAssetList will still hold the version of the file when this collection was last loaded or saved successfully so nothing will be out of sync. // If the user closes the editor before successfully saving, this file may not be exactly what was seen at the time the editor closed. UE_LOG(LogCollectionManager, Warning, TEXT("Failed to revert a checked out collection after failing to save or checkin: %s"), *CollectionName.ToString()); } } } } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bSaveSuccessful ) { // Files are always saved at the latest version as loading should take care of data upgrades FileVersion = ECollectionVersion::CurrentVersion; DiskSnapshot.TakeSnapshot(*this); } GWarn->EndSlowTask(); UE_LOG(LogCollectionManager, Verbose, TEXT("Saved collection %s in %0.6f seconds"), *CollectionName.ToString(), FPlatformTime::Seconds() - SaveStartTime); return bSaveSuccessful; }
bool FCollection::Save(FText& OutError) { if ( !ensure(SourceFilename.Len()) ) { OutError = LOCTEXT("Error_Internal", "There was an internal error."); return false; } // Store the start time for profiling reasons double SaveStartTime = FPlatformTime::Seconds(); // Keep track of save progress to update the slow task dialog const int32 SaveProgressDenominator = 3; int32 SaveProgressNumerator = 0; GWarn->BeginSlowTask( FText::Format( LOCTEXT("SavingCollection", "Saving Collection {0}"), FText::FromName( CollectionName ) ), true); GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bUseSCC ) { // Checkout the file if ( !CheckoutCollection(OutError) ) { UE_LOG(LogCollectionManager, Error, TEXT("Failed to check out a collection file: %s"), *CollectionName.ToString()); GWarn->EndSlowTask(); return false; } } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); // Generate a string with the file contents FString FileOutput; // Start with the header TMap<FString,FString> HeaderPairs; GenerateHeaderPairs(HeaderPairs); for (TMap<FString,FString>::TConstIterator HeaderIt(HeaderPairs); HeaderIt; ++HeaderIt) { FileOutput += HeaderIt.Key() + TEXT(":") + HeaderIt.Value() + LINE_TERMINATOR; } FileOutput += LINE_TERMINATOR; // Now for the content if ( IsDynamic() ) { // @todo Dynamic collections } else { // Static collection. Save a flat list of all assets in the collection. for (int32 AssetIdx = 0; AssetIdx < AssetList.Num(); ++AssetIdx) { FileOutput += AssetList[AssetIdx].ToString() + LINE_TERMINATOR; } } // Attempt to save the file bool bSaveSuccessful = false; if ( ensure(FileOutput.Len()) ) { // We have some output, write it to file if ( FFileHelper::SaveStringToFile(FileOutput, *SourceFilename) ) { bSaveSuccessful = true; } else { OutError = LOCTEXT("Error_WriteFailed", "Failed to write to collection file."); UE_LOG(LogCollectionManager, Error, TEXT("%s %s"), *OutError.ToString(), *CollectionName.ToString()); } } else { OutError = LOCTEXT("Error_Internal", "There was an internal error."); } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bSaveSuccessful ) { if ( bUseSCC ) { // Check in the file if the save was successful if ( bSaveSuccessful ) { if ( !CheckinCollection(OutError) ) { UE_LOG(LogCollectionManager, Error, TEXT("Failed to check in a collection successfully saving: %s"), *CollectionName.ToString()); bSaveSuccessful = false; } } // If the save was not successful or the checkin failed, revert if ( !bSaveSuccessful ) { FText Unused; if ( !RevertCollection(Unused) ) { // The revert failed... file will be left on disk as it was saved. // DiskAssetList will still hold the version of the file when this collection was last loaded or saved successfully so nothing will be out of sync. // If the user closes the editor before successfully saving, this file may not be exactly what was seen at the time the editor closed. UE_LOG(LogCollectionManager, Warning, TEXT("Failed to revert a checked out collection after failing to save or checkin: %s"), *CollectionName.ToString()); } } } } GWarn->UpdateProgress(SaveProgressNumerator++, SaveProgressDenominator); if ( bSaveSuccessful ) { DiskAssetList = AssetList; } GWarn->EndSlowTask(); UE_LOG(LogCollectionManager, Verbose, TEXT("Saved collection %s in %0.6f seconds"), *CollectionName.ToString(), FPlatformTime::Seconds() - SaveStartTime); return bSaveSuccessful; }