コード例 #1
0
void FCollectionManager::LoadCollections()
{
	const double LoadStartTime = FPlatformTime::Seconds();
	int32 NumCollectionsLoaded = 0;

	for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx)
	{
		const FString& CollectionFolder = CollectionFolders[CacheIdx];
		const FString WildCard = FString::Printf(TEXT("%s/*.%s"), *CollectionFolder, *CollectionExtension);

		TArray<FString> Filenames;
		IFileManager::Get().FindFiles(Filenames, *WildCard, true, false);

		for (int32 FileIdx = 0; FileIdx < Filenames.Num(); ++FileIdx)
		{
			const FString Filename = CollectionFolder / Filenames[FileIdx];

			FCollection Collection;
			const bool bUseSCC = ShouldUseSCC(ECollectionShareType::Type(CacheIdx));
			if ( Collection.LoadFromFile(Filename, bUseSCC) )
			{
				AddCollection(Collection, ECollectionShareType::Type(CacheIdx));
			}
			else
			{
				UE_LOG(LogCollectionManager, Warning, TEXT("Failed to load collection file %s"), *Filename);
			}
		}
		
		NumCollectionsLoaded += CachedCollections[CacheIdx].Num();
	}

	UE_LOG( LogCollectionManager, Log, TEXT( "Loaded %d collections in %0.6f seconds" ), NumCollectionsLoaded, FPlatformTime::Seconds() - LoadStartTime );
}
コード例 #2
0
bool FCollectionManager::DestroyCollection(FName CollectionName, ECollectionShareType::Type ShareType)
{
	if ( !ensure(ShareType < ECollectionShareType::CST_All) )
	{
		// Bad share type
		LastError = LOCTEXT("Error_Internal", "There was an internal error.");
		return false;
	}

	FCollection** CollectionPtr = CachedCollections[ShareType].Find(CollectionName);
	if (CollectionPtr != NULL && ensure(*CollectionPtr != NULL) )
	{
		FCollection* Collection = *CollectionPtr;
		
		if ( Collection->DeleteSourceFile(LastError) )
		{
			RemoveCollection(Collection, ShareType);
			CollectionDestroyedEvent.Broadcast( FCollectionNameType( CollectionName, ShareType ) );
			return true;
		}
		else
		{
			// Failed to delete the source file
			return false;
		}
	}
	else
	{
		// The collection doesn't exist
		LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
		return false;
	}
}
コード例 #3
0
bool FCollectionManager::IsCollectionEmpty(FName CollectionName, ECollectionShareType::Type ShareType)
{
	if ( !ensure(ShareType < ECollectionShareType::CST_All) )
	{
		// Bad share type
		LastError = LOCTEXT("Error_Internal", "There was an internal error.");
		return true;
	}

	FCollection*const* CollectionPtr = CachedCollections[ShareType].Find(CollectionName);
	FCollection* Collection = NULL;

	if ( CollectionPtr )
	{
		Collection = *CollectionPtr;
		ensure(Collection);
	}

	if ( Collection )
	{
		return Collection->IsEmpty();
	}

	return true;
}
コード例 #4
0
bool FCollectionManager::GetAssetsInCollection(FName CollectionName, ECollectionShareType::Type ShareType, TArray<FName>& AssetsPaths) const
{
	if ( ShareType == ECollectionShareType::CST_All )
	{
		// Asked for all share types, find assets in the specified collection name in any cache
		bool bFoundAssets = false;

		for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx)
		{
			if ( GetAssetsInCollection(CollectionName, ECollectionShareType::Type(CacheIdx), AssetsPaths) )
			{
				bFoundAssets = true;
			}
		}

		return bFoundAssets;
	}
	else
	{
		FCollection*const* CollectionPtr = CachedCollections[ShareType].Find(CollectionName);
		FCollection* Collection = NULL;
	
		if (CollectionPtr)
		{
			Collection = *CollectionPtr;
			ensure(Collection);
		}

		if ( Collection )
		{
			Collection->GetAssetsInCollection(AssetsPaths);
			return true;
		}

		return false;
	}
}
コード例 #5
0
bool FCollectionManager::CreateCollection(FName CollectionName, ECollectionShareType::Type ShareType)
{
	if ( !ensure(ShareType < ECollectionShareType::CST_All) )
	{
		// Bad share type
		LastError = LOCTEXT("Error_Internal", "There was an internal error.");
		return false;
	}

	// Try to add the collection
	bool bUseSCC = ShouldUseSCC(ShareType);
	FString SourceFolder = CollectionFolders[ShareType];

	FCollection NewCollection(CollectionName, SourceFolder, CollectionExtension, bUseSCC);
	FCollection* Collection = AddCollection(NewCollection, ShareType);

	if ( !Collection )
	{
		// Failed to add the collection, it already exists
		LastError = LOCTEXT("Error_AlreadyExists", "The collection already exists.");
		return false;
	}

	if ( Collection->Save(LastError) )
	{
		// Collection saved!
		CollectionCreatedEvent.Broadcast( FCollectionNameType( CollectionName, ShareType ) );
		return true;
	}
	else
	{
		// Collection failed to save, remove it from the cache
		RemoveCollection(Collection, ShareType);
		return false;
	}
}
コード例 #6
0
bool FCollectionManager::RemoveFromCollection(FName CollectionName, ECollectionShareType::Type ShareType, const TArray<FName>& ObjectPaths, int32* OutNumRemoved)
{
	if ( OutNumRemoved )
	{
		*OutNumRemoved = 0;
	}

	if ( !ensure(ShareType < ECollectionShareType::CST_All) )
	{
		// Bad share type
		LastError = LOCTEXT("Error_Internal", "There was an internal error.");
		return false;
	}

	FCollection** CollectionPtr = CachedCollections[ShareType].Find(CollectionName);
	if (CollectionPtr != NULL)
	{
		FCollection* Collection = *CollectionPtr;
		
		TArray<FName> RemovedAssets;
		for (int32 ObjectIdx = 0; ObjectIdx < ObjectPaths.Num(); ++ObjectIdx)
		{
			const FName& ObjectPath = ObjectPaths[ObjectIdx];

			if ( Collection->RemoveAssetFromCollection(ObjectPath) )
			{
				RemovedAssets.Add(ObjectPath);
			}
		}

		if ( RemovedAssets.Num() == 0 )
		{
			// Failed to remove, none of the objects were in the collection
			LastError = LOCTEXT("Error_NotInCollection", "None of the assets were in the collection.");
			return false;
		}
			
		if ( Collection->Save(LastError) )
		{
			// Removed and saved
			if ( OutNumRemoved )
			{
				*OutNumRemoved = RemovedAssets.Num();
			}

			FCollectionNameType CollectionNameType( Collection->GetCollectionName(), ShareType );
			AssetsRemovedEvent.Broadcast( CollectionNameType, ObjectPaths );
			return true;
		}
		else
		{
			// Removed but not saved, revert the remove
			for (int32 AssetIdx = 0; AssetIdx < RemovedAssets.Num(); ++AssetIdx)
			{
				Collection->AddAssetToCollection(RemovedAssets[AssetIdx]);
			}
			return false;
		}
	}
	else
	{
		// Collection not found
		LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
		return false;
	}
}
コード例 #7
0
bool FCollectionManager::AddToCollection(FName CollectionName, ECollectionShareType::Type ShareType, const TArray<FName>& ObjectPaths, int32* OutNumAdded)
{
	if ( OutNumAdded )
	{
		*OutNumAdded = 0;
	}

	if ( !ensure(ShareType < ECollectionShareType::CST_All) )
	{
		// Bad share type
		LastError = LOCTEXT("Error_Internal", "There was an internal error.");
		return false;
	}

	FCollection** CollectionPtr = CachedCollections[ShareType].Find(CollectionName);
	FCollection* Collection = NULL;
	if (CollectionPtr != NULL)
	{
		Collection = *CollectionPtr;
	}
	else
	{
		// Collection doesn't exist
		LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
		return false;
	}

	if ( ensure(Collection) )
	{
		int32 NumAdded = 0;
		for (int32 ObjectIdx = 0; ObjectIdx < ObjectPaths.Num(); ++ObjectIdx)
		{
			if ( Collection->AddAssetToCollection(ObjectPaths[ObjectIdx]) )
			{
				NumAdded++;
			}
		}

		if ( NumAdded > 0 )
		{
			if ( Collection->Save(LastError) )
			{
				// Added and saved
				if ( OutNumAdded )
				{
					*OutNumAdded = NumAdded;
				}

				FCollectionNameType CollectionNameType( Collection->GetCollectionName(), ShareType );
				AssetsAddedEvent.Broadcast( CollectionNameType, ObjectPaths );
				return true;
			}
			else
			{
				// Added but not saved, revert the add
				for (int32 ObjectIdx = 0; ObjectIdx < ObjectPaths.Num(); ++ObjectIdx)
				{
					Collection->RemoveAssetFromCollection(ObjectPaths[ObjectIdx]);
				}
				return false;
			}
		}
		else
		{
			// Failed to add, all of the objects were already in the collection
			LastError = LOCTEXT("Error_AlreadyInCollection", "All of the assets were already in the collection.");
			return false;
		}
	}
	else
	{
		// Collection was never found. Perhaps it was null in the TMap
		LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
		return false;
	}
}
コード例 #8
0
bool FCollection::DeleteFromSourceControl(FText& OutError)
{
	ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
	if ( !ISourceControlModule::Get().IsEnabled() )
	{
		OutError = LOCTEXT("Error_SCCDisabled", "Source control is not enabled. Enable source control in the preferences menu.");
		return false;
	}

	if ( !SourceControlProvider.IsAvailable() )
	{
		OutError = LOCTEXT("Error_SCCNotAvailable", "Source control is currently not available. Check your connection and try again.");
		return false;
	}

	bool bDeletedSuccessfully = false;

	const int32 DeleteProgressDenominator = 2;
	int32 DeleteProgressNumerator = 0;

	const FText CollectionNameText = FText::FromName( CollectionName );

	FFormatNamedArguments Args;
	Args.Add( TEXT("CollectionName"), CollectionNameText );
	const FText StatusUpdate = FText::Format( LOCTEXT("DeletingCollection", "Deleting Collection {CollectionName}"), Args );

	GWarn->BeginSlowTask( StatusUpdate, true );
	GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator);

	FString AbsoluteFilename = FPaths::ConvertRelativePathToFull(SourceFilename);
	FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);
	
	GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator);

	// If checked out locally for some reason, revert
	if (SourceControlState.IsValid() && (SourceControlState->IsAdded() || SourceControlState->IsCheckedOut() || SourceControlState->IsDeleted()))
	{
		if ( !RevertCollection(OutError) )
		{
			// Failed to revert, just bail out
			GWarn->EndSlowTask();
			return false;
		}

		// Make sure we get a fresh state from the server
		SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);
	}

	// If not at the head revision, sync up
	if (SourceControlState.IsValid() && !SourceControlState->IsCurrent())
	{
		if ( !SourceControlProvider.Execute(ISourceControlOperation::Create<FSync>(), AbsoluteFilename) )
		{
			// Could not sync up with the head revision
			GWarn->EndSlowTask();
			OutError = LOCTEXT("Error_SCCSync", "Failed to sync collection to the head revision.");
			return false;
		}

		// Check to see if the file exists at the head revision
		if ( IFileManager::Get().FileSize(*SourceFilename) < 0 )
		{
			// File was already deleted, consider this a success
			GWarn->EndSlowTask();
			return true;
		}
			
		FCollection NewCollection;
				
		if ( !NewCollection.LoadFromFile(SourceFilename, false) )
		{
			// Failed to load the head revision file so it isn't safe to delete it
			GWarn->EndSlowTask();
			OutError = LOCTEXT("Error_SCCBadHead", "Failed to load the collection at the head revision.");
			return false;
		}

		// Loaded the head revision, now merge up so the files are in a consistent state
		MergeWithCollection(NewCollection);

		// Make sure we get a fresh state from the server
		SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);
	}

	GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator);

	if(SourceControlState.IsValid())
	{
		if(SourceControlState->IsAdded() || SourceControlState->IsCheckedOut())
		{
			OutError = LOCTEXT("Error_SCCDeleteWhileCheckedOut", "Failed to delete collection in source control because it is checked out or open for add.");
		}
		else if(SourceControlState->CanCheckout())
		{
			if ( SourceControlProvider.Execute(ISourceControlOperation::Create<FDelete>(), AbsoluteFilename) )
			{
				// Now check in the delete
				const FText ChangelistDesc = FText::Format( LOCTEXT("CollectionDeletedDesc", "Deleted collection: {CollectionName}"), CollectionNameText );
				TSharedRef<FCheckIn, ESPMode::ThreadSafe> CheckInOperation = ISourceControlOperation::Create<FCheckIn>();
				CheckInOperation->SetDescription(ChangelistDesc.ToString());
				if ( SourceControlProvider.Execute( CheckInOperation, AbsoluteFilename ) )
				{
					// Deleted successfully!
					bDeletedSuccessfully = true;
				}
				else
				{
					FText Unused;
					if ( !RevertCollection(Unused) )
					{
						UE_LOG(LogCollectionManager, Warning, TEXT("Failed to revert collection '%s' after failing to check in the file that was marked for delete."), *CollectionName.ToString());
					}

					OutError = LOCTEXT("Error_SCCCheckIn", "Failed to check in collection.");
				}
			}
			else
			{
				OutError = LOCTEXT("Error_SCCDeleteFailed", "Failed to delete collection in source control.");
			}
		}
		else if(!SourceControlState->IsSourceControlled())
		{
			// Not yet in the depot or deleted. We can just delete it from disk.
			bDeletedSuccessfully = IFileManager::Get().Delete(*AbsoluteFilename);
			if ( !bDeletedSuccessfully )
			{
				OutError = LOCTEXT("Error_DiskDeleteFailed", "Failed to delete the collection file from disk.");
			}
		}
		else if (!SourceControlState->IsCurrent())
		{
			OutError = LOCTEXT("Error_SCCNotCurrent", "Collection is not at head revision after sync.");
		}
		else if(SourceControlState->IsCheckedOutOther())
		{
			OutError = LOCTEXT("Error_SCCCheckedOutOther", "Collection is checked out by another user.");
		}
		else
		{
			OutError = LOCTEXT("Error_SCCUnknown", "Could not determine source control state.");
		}
	}
	else
	{
		OutError = LOCTEXT("Error_SCCInvalid", "Source control state is invalid.");
	}

	GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator);

	GWarn->EndSlowTask();

	return bDeletedSuccessfully;
}
コード例 #9
0
bool FCollection::CheckoutCollection(FText& OutError)
{
	if ( !ensure(SourceFilename.Len()) )
	{
		OutError = LOCTEXT("Error_Internal", "There was an internal error.");
		return false;
	}

	ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
	if ( !ISourceControlModule::Get().IsEnabled() )
	{
		OutError = LOCTEXT("Error_SCCDisabled", "Source control is not enabled. Enable source control in the preferences menu.");
		return false;
	}

	if ( !SourceControlProvider.IsAvailable() )
	{
		OutError = LOCTEXT("Error_SCCNotAvailable", "Source control is currently not available. Check your connection and try again.");
		return false;
	}

	FString AbsoluteFilename = FPaths::ConvertRelativePathToFull(SourceFilename);
	FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);

	bool bSuccessfullyCheckedOut = false;
	TArray<FString> FilesToBeCheckedOut;
	FilesToBeCheckedOut.Add(AbsoluteFilename);

	if (SourceControlState.IsValid() && SourceControlState->IsDeleted())
	{
		// Revert our delete
		if ( !RevertCollection(OutError) )
		{
			return false;
		}

		// Make sure we get a fresh state from the server
		SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);
	}

	// If not at the head revision, sync up
	if (SourceControlState.IsValid() && !SourceControlState->IsCurrent())
	{
		if ( !SourceControlProvider.Execute(ISourceControlOperation::Create<FSync>(), FilesToBeCheckedOut) )
		{
			// Could not sync up with the head revision
			OutError = LOCTEXT("Error_SCCSync", "Failed to sync collection to the head revision.");
			return false;
		}

		// Check to see if the file exists at the head revision
		if ( IFileManager::Get().FileSize(*SourceFilename) < 0 )
		{
			// File was deleted at head...
			// Just add our changes to an empty list so we can mark it for add
			FCollection NewCollection;
			MergeWithCollection(NewCollection);
		}
		else
		{
			// File found! Load it and merge with our local changes
			FCollection NewCollection;
			if ( !NewCollection.LoadFromFile(SourceFilename, false) )
			{
				// Failed to load the head revision file so it isn't safe to delete it
				OutError = LOCTEXT("Error_SCCBadHead", "Failed to load the collection at the head revision.");
				return false;
			}

			// Loaded the head revision, now merge up so the files are in a consistent state
			MergeWithCollection(NewCollection);
		}

		// Make sure we get a fresh state from the server
		SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate);
	}

	if(SourceControlState.IsValid())
	{
		if(SourceControlState->IsAdded() || SourceControlState->IsCheckedOut())
		{
			// Already checked out or opened for add
			bSuccessfullyCheckedOut = true;
		}
		else if(SourceControlState->CanCheckout())
		{
			// In depot and needs to be checked out
			bSuccessfullyCheckedOut = (SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), FilesToBeCheckedOut) == ECommandResult::Succeeded);
			if (!bSuccessfullyCheckedOut)
			{
				OutError = LOCTEXT("Error_SCCCheckout", "Failed to check out collection.");
			}
		}
		else if(!SourceControlState->IsSourceControlled())
		{
			// Not yet in the depot. Add it.
			bSuccessfullyCheckedOut = (SourceControlProvider.Execute(ISourceControlOperation::Create<FMarkForAdd>(), FilesToBeCheckedOut) == ECommandResult::Succeeded);
			if (!bSuccessfullyCheckedOut)
			{
				OutError = LOCTEXT("Error_SCCAdd", "Failed to add new collection to source control.");
			}
		}
		else if(!SourceControlState->IsCurrent())
		{
			OutError = LOCTEXT("Error_SCCNotCurrent", "Collection is not at head revision after sync.");
		}
		else if(SourceControlState->IsCheckedOutOther())
		{
			OutError = LOCTEXT("Error_SCCCheckedOutOther", "Collection is checked out by another user.");
		}
		else
		{
			OutError = LOCTEXT("Error_SCCUnknown", "Could not determine source control state.");
		}
	}
	else
	{
		OutError = LOCTEXT("Error_SCCInvalid", "Source control state is invalid.");
	}

	return bSuccessfullyCheckedOut;
}