2014-12-07 19:09:38 -05:00
|
|
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
#include "CollectionManagerPrivatePCH.h"
|
|
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "CollectionManager"
|
|
|
|
|
|
|
|
|
|
FCollectionManager::FCollectionManager()
|
|
|
|
|
{
|
|
|
|
|
LastError = LOCTEXT("Error_Unknown", "None");
|
|
|
|
|
|
|
|
|
|
CollectionFolders[ECollectionShareType::CST_Local] = FPaths::GameSavedDir() / TEXT("Collections");
|
|
|
|
|
CollectionFolders[ECollectionShareType::CST_Private] = FPaths::GameUserDeveloperDir() / TEXT("Collections");
|
|
|
|
|
CollectionFolders[ECollectionShareType::CST_Shared] = FPaths::GameContentDir() / TEXT("Collections");
|
|
|
|
|
|
|
|
|
|
CollectionExtension = TEXT("collection");
|
|
|
|
|
|
|
|
|
|
LoadCollections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FCollectionManager::~FCollectionManager()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
bool FCollectionManager::HasCollections() const
|
|
|
|
|
{
|
|
|
|
|
return CachedCollections.Num() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void FCollectionManager::GetCollectionNames(ECollectionShareType::Type ShareType, TArray<FName>& CollectionNames) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
for (const auto& CachedCollection : CachedCollections)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType& CollectionKey = CachedCollection.Key;
|
|
|
|
|
if (ShareType == ECollectionShareType::CST_All || ShareType == CollectionKey.Type)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
CollectionNames.Add(CollectionKey.Name);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::CollectionExists(FName CollectionName, ECollectionShareType::Type ShareType) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (ShareType == ECollectionShareType::CST_All)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
// Asked to check all share types...
|
2014-03-14 14:13:41 -04:00
|
|
|
for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (CachedCollections.Contains(FCollectionNameType(CollectionName, ECollectionShareType::Type(CacheIdx))))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Collection exists in at least one cache
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collection not found in any cache
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
return CachedCollections.Contains(FCollectionNameType(CollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::GetAssetsInCollection(FName CollectionName, ECollectionShareType::Type ShareType, TArray<FName>& AssetsPaths) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
auto GetAssetsInCollectionInternal = [this, &AssetsPaths](const FCollectionNameType& InCollectionKey) -> bool
|
|
|
|
|
{
|
|
|
|
|
const TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(InCollectionKey);
|
|
|
|
|
if (CollectionRefPtr)
|
|
|
|
|
{
|
|
|
|
|
(*CollectionRefPtr)->GetAssetsInCollection(AssetsPaths);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (ShareType == ECollectionShareType::CST_All)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
bFoundAssets |= GetAssetsInCollectionInternal(FCollectionNameType(CollectionName, ECollectionShareType::Type(CacheIdx)));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
return bFoundAssets;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
return GetAssetsInCollectionInternal(FCollectionNameType(CollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::GetClassesInCollection(FName CollectionName, ECollectionShareType::Type ShareType, TArray<FName>& ClassPaths) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
auto GetClassesInCollectionInternal = [this, &ClassPaths](const FCollectionNameType& InCollectionKey) -> bool
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
const TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(InCollectionKey);
|
|
|
|
|
if (CollectionRefPtr)
|
|
|
|
|
{
|
|
|
|
|
(*CollectionRefPtr)->GetClassesInCollection(ClassPaths);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (ShareType == ECollectionShareType::CST_All)
|
|
|
|
|
{
|
|
|
|
|
// Asked for all share types, find classes in the specified collection name in any cache
|
|
|
|
|
bool bFoundAssets = false;
|
2014-03-14 14:13:41 -04:00
|
|
|
for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
bFoundAssets |= GetClassesInCollectionInternal(FCollectionNameType(CollectionName, ECollectionShareType::Type(CacheIdx)));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
return bFoundAssets;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
return GetClassesInCollectionInternal(FCollectionNameType(CollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::GetObjectsInCollection(FName CollectionName, ECollectionShareType::Type ShareType, TArray<FName>& ObjectPaths) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
auto GetObjectsInCollectionInternal = [this, &ObjectPaths](const FCollectionNameType& InCollectionKey) -> bool
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
const TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(InCollectionKey);
|
|
|
|
|
if (CollectionRefPtr)
|
|
|
|
|
{
|
|
|
|
|
(*CollectionRefPtr)->GetObjectsInCollection(ObjectPaths);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (ShareType == ECollectionShareType::CST_All)
|
|
|
|
|
{
|
|
|
|
|
// Asked for all share types, find objects in the specified collection name in any cache
|
|
|
|
|
bool bFoundAssets = false;
|
2014-03-14 14:13:41 -04:00
|
|
|
for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
bFoundAssets |= GetObjectsInCollectionInternal(FCollectionNameType(CollectionName, ECollectionShareType::Type(CacheIdx)));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
return bFoundAssets;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
return GetObjectsInCollectionInternal(FCollectionNameType(CollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
void FCollectionManager::GetCollectionsContainingObject(FName ObjectPath, ECollectionShareType::Type ShareType, TArray<FName>& OutCollectionNames) const
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-29 13:15:23 -04:00
|
|
|
const auto* ObjectCollectionsPtr = CachedObjects.Find(ObjectPath);
|
|
|
|
|
if (ObjectCollectionsPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-29 13:15:23 -04:00
|
|
|
for (const FCollectionNameType& CollectionKey : *ObjectCollectionsPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-29 13:15:23 -04:00
|
|
|
if (ShareType == ECollectionShareType::CST_All || ShareType == CollectionKey.Type)
|
|
|
|
|
{
|
|
|
|
|
OutCollectionNames.Add(CollectionKey.Name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FCollectionManager::GetCollectionsContainingObject(FName ObjectPath, TArray<FCollectionNameType>& OutCollections) const
|
|
|
|
|
{
|
|
|
|
|
const auto* ObjectCollectionsPtr = CachedObjects.Find(ObjectPath);
|
|
|
|
|
if (ObjectCollectionsPtr)
|
|
|
|
|
{
|
|
|
|
|
OutCollections.Append(*ObjectCollectionsPtr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FCollectionManager::GetCollectionsContainingObjects(const TArray<FName>& ObjectPaths, TMap<FCollectionNameType, TArray<FName>>& OutCollectionsAndMatchedObjects) const
|
|
|
|
|
{
|
|
|
|
|
for (const FName& ObjectPath : ObjectPaths)
|
|
|
|
|
{
|
|
|
|
|
const auto* ObjectCollectionsPtr = CachedObjects.Find(ObjectPath);
|
|
|
|
|
if (ObjectCollectionsPtr)
|
|
|
|
|
{
|
|
|
|
|
for (const FCollectionNameType& CollectionKey : *ObjectCollectionsPtr)
|
|
|
|
|
{
|
|
|
|
|
TArray<FName>& MatchedObjects = OutCollectionsAndMatchedObjects.FindOrAdd(CollectionKey);
|
|
|
|
|
MatchedObjects.Add(ObjectPath);
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 09:23:51 -04:00
|
|
|
FString FCollectionManager::GetCollectionsStringForObject(FName ObjectPath, ECollectionShareType::Type ShareType) const
|
|
|
|
|
{
|
2015-05-29 13:15:23 -04:00
|
|
|
const auto* ObjectCollectionsPtr = CachedObjects.Find(ObjectPath);
|
|
|
|
|
if (ObjectCollectionsPtr)
|
|
|
|
|
{
|
|
|
|
|
TArray<FString> CollectionNameStrings;
|
2015-05-21 09:23:51 -04:00
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
for (const FCollectionNameType& CollectionKey : *ObjectCollectionsPtr)
|
2015-05-21 09:23:51 -04:00
|
|
|
{
|
2015-05-29 13:15:23 -04:00
|
|
|
if (ShareType == ECollectionShareType::CST_All || ShareType == CollectionKey.Type)
|
|
|
|
|
{
|
|
|
|
|
CollectionNameStrings.Add(CollectionKey.Name.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CollectionNameStrings.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
CollectionNameStrings.Sort();
|
|
|
|
|
return FString::Join(CollectionNameStrings, TEXT(", "));
|
2015-05-21 09:23:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void FCollectionManager::CreateUniqueCollectionName(const FName& BaseName, ECollectionShareType::Type ShareType, FName& OutCollectionName) const
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType != ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 IntSuffix = 1;
|
|
|
|
|
bool CollectionAlreadyExists = false;
|
|
|
|
|
do
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (IntSuffix <= 1)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
OutCollectionName = BaseName;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OutCollectionName = *FString::Printf(TEXT("%s%d"), *BaseName.ToString(), IntSuffix);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
CollectionAlreadyExists = CachedCollections.Contains(FCollectionNameType(OutCollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
++IntSuffix;
|
|
|
|
|
}
|
2015-05-21 07:43:16 -04:00
|
|
|
while (CollectionAlreadyExists);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::CreateCollection(FName CollectionName, ECollectionShareType::Type ShareType)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// 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];
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
TSharedRef<FCollection> NewCollection = MakeShareable(new FCollection(CollectionName, SourceFolder, CollectionExtension, bUseSCC));
|
|
|
|
|
if (!AddCollection(NewCollection, ShareType))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to add the collection, it already exists
|
|
|
|
|
LastError = LOCTEXT("Error_AlreadyExists", "The collection already exists.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (NewCollection->Save(LastError))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Collection saved!
|
2015-05-21 07:43:16 -04:00
|
|
|
CollectionCreatedEvent.Broadcast(FCollectionNameType(CollectionName, ShareType));
|
2014-03-14 14:13:41 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Collection failed to save, remove it from the cache
|
2015-05-21 07:43:16 -04:00
|
|
|
RemoveCollection(NewCollection, ShareType);
|
2014-03-14 14:13:41 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
bool FCollectionManager::RenameCollection(FName CurrentCollectionName, ECollectionShareType::Type CurrentShareType, FName NewCollectionName, ECollectionShareType::Type NewShareType)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(CurrentShareType < ECollectionShareType::CST_All) || !ensure(NewShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the object paths for the assets in the collection
|
|
|
|
|
TArray<FName> ObjectPaths;
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!GetAssetsInCollection(CurrentCollectionName, CurrentShareType, ObjectPaths))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to get assets in the current collection
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new collection
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!CreateCollection(NewCollectionName, NewShareType))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to create collection
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (ObjectPaths.Num() > 0)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Add all the objects from the old collection to the new collection
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!AddToCollection(NewCollectionName, NewShareType, ObjectPaths))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to add paths to the new collection. Destroy the collection we created.
|
|
|
|
|
DestroyCollection(NewCollectionName, NewShareType);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete the old collection
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!DestroyCollection(CurrentCollectionName, CurrentShareType))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to destroy the old collection. Destroy the collection we created.
|
|
|
|
|
DestroyCollection(NewCollectionName, NewShareType);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
RebuildCachedObjects();
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
// Success
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType OriginalCollectionKey(CurrentCollectionName, CurrentShareType);
|
|
|
|
|
const FCollectionNameType NewCollectionKey(NewCollectionName, NewShareType);
|
|
|
|
|
CollectionRenamedEvent.Broadcast(OriginalCollectionKey, NewCollectionKey);
|
2014-03-14 14:13:41 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::DestroyCollection(FName CollectionName, ECollectionShareType::Type ShareType)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType CollectionKey(CollectionName, ShareType);
|
|
|
|
|
TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(CollectionKey);
|
|
|
|
|
if (!CollectionRefPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// The collection doesn't exist
|
|
|
|
|
LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-05-21 07:43:16 -04:00
|
|
|
|
|
|
|
|
if ((*CollectionRefPtr)->DeleteSourceFile(LastError))
|
|
|
|
|
{
|
|
|
|
|
RemoveCollection(*CollectionRefPtr, ShareType);
|
2015-05-29 13:15:23 -04:00
|
|
|
|
|
|
|
|
RebuildCachedObjects();
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
CollectionDestroyedEvent.Broadcast(CollectionKey);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Failed to delete the source file
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
bool FCollectionManager::AddToCollection(FName CollectionName, ECollectionShareType::Type ShareType, FName ObjectPath)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
TArray<FName> Paths;
|
|
|
|
|
Paths.Add(ObjectPath);
|
|
|
|
|
return AddToCollection(CollectionName, ShareType, Paths);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::AddToCollection(FName CollectionName, ECollectionShareType::Type ShareType, const TArray<FName>& ObjectPaths, int32* OutNumAdded)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (OutNumAdded)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
*OutNumAdded = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType CollectionKey(CollectionName, ShareType);
|
|
|
|
|
TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(CollectionKey);
|
|
|
|
|
if (!CollectionRefPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Collection doesn't exist
|
|
|
|
|
LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
int32 NumAdded = 0;
|
|
|
|
|
for (const FName& ObjectPath : ObjectPaths)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if ((*CollectionRefPtr)->AddAssetToCollection(ObjectPath))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
NumAdded++;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2015-05-21 07:43:16 -04:00
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (NumAdded > 0)
|
|
|
|
|
{
|
|
|
|
|
if ((*CollectionRefPtr)->Save(LastError))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
// Added and saved
|
|
|
|
|
if (OutNumAdded)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
*OutNumAdded = NumAdded;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
RebuildCachedObjects();
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
AssetsAddedEvent.Broadcast(CollectionKey, ObjectPaths);
|
|
|
|
|
return true;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
// Added but not saved, revert the add
|
|
|
|
|
for (const FName& ObjectPath : ObjectPaths)
|
|
|
|
|
{
|
|
|
|
|
(*CollectionRefPtr)->RemoveAssetFromCollection(ObjectPath);
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
// 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.");
|
2014-03-14 14:13:41 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::RemoveFromCollection(FName CollectionName, ECollectionShareType::Type ShareType, FName ObjectPath)
|
|
|
|
|
{
|
|
|
|
|
TArray<FName> Paths;
|
|
|
|
|
Paths.Add(ObjectPath);
|
|
|
|
|
return RemoveFromCollection(CollectionName, ShareType, Paths);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::RemoveFromCollection(FName CollectionName, ECollectionShareType::Type ShareType, const TArray<FName>& ObjectPaths, int32* OutNumRemoved)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (OutNumRemoved)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
*OutNumRemoved = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType CollectionKey(CollectionName, ShareType);
|
|
|
|
|
TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(CollectionKey);
|
|
|
|
|
if (!CollectionRefPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Collection not found
|
|
|
|
|
LastError = LOCTEXT("Error_DoesntExist", "The collection doesn't exist.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-05-21 07:43:16 -04:00
|
|
|
|
|
|
|
|
TArray<FName> RemovedAssets;
|
|
|
|
|
for (const FName& ObjectPath : ObjectPaths)
|
|
|
|
|
{
|
|
|
|
|
if ((*CollectionRefPtr)->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 ((*CollectionRefPtr)->Save(LastError))
|
|
|
|
|
{
|
|
|
|
|
// Removed and saved
|
|
|
|
|
if (OutNumRemoved)
|
|
|
|
|
{
|
|
|
|
|
*OutNumRemoved = RemovedAssets.Num();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
RebuildCachedObjects();
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
AssetsRemovedEvent.Broadcast(CollectionKey, ObjectPaths);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Removed but not saved, revert the remove
|
|
|
|
|
for (const FName& RemovedAssetName : RemovedAssets)
|
|
|
|
|
{
|
|
|
|
|
(*CollectionRefPtr)->AddAssetToCollection(RemovedAssetName);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::EmptyCollection(FName CollectionName, ECollectionShareType::Type ShareType)
|
|
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TArray<FName> ObjectPaths;
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!GetAssetsInCollection(CollectionName, ShareType, ObjectPaths))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Failed to load collection
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
if (ObjectPaths.Num() == 0)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Collection already empty
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
if (RemoveFromCollection(CollectionName, ShareType, ObjectPaths))
|
|
|
|
|
{
|
|
|
|
|
RebuildCachedObjects();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
bool FCollectionManager::IsCollectionEmpty(FName CollectionName, ECollectionShareType::Type ShareType) const
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType CollectionKey(CollectionName, ShareType);
|
|
|
|
|
const TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(CollectionKey);
|
|
|
|
|
if (CollectionRefPtr)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
return (*CollectionRefPtr)->IsEmpty();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:15:23 -04:00
|
|
|
bool FCollectionManager::IsObjectInCollection(FName ObjectPath, FName CollectionName, ECollectionShareType::Type ShareType) const
|
|
|
|
|
{
|
|
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
|
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
LastError = LOCTEXT("Error_Internal", "There was an internal error.");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FCollectionNameType CollectionKey(CollectionName, ShareType);
|
|
|
|
|
const TSharedRef<FCollection>* const CollectionRefPtr = CachedCollections.Find(CollectionKey);
|
|
|
|
|
if (CollectionRefPtr)
|
|
|
|
|
{
|
|
|
|
|
return (*CollectionRefPtr)->IsObjectInCollection(ObjectPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void FCollectionManager::LoadCollections()
|
|
|
|
|
{
|
|
|
|
|
const double LoadStartTime = FPlatformTime::Seconds();
|
2015-05-21 07:43:16 -04:00
|
|
|
const int32 PrevNumCollections = CachedCollections.Num();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
for (const FString& BaseFilename : Filenames)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
const FString Filename = CollectionFolder / BaseFilename;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
TSharedRef<FCollection> NewCollection = MakeShareable(new FCollection());
|
2014-03-14 14:13:41 -04:00
|
|
|
const bool bUseSCC = ShouldUseSCC(ECollectionShareType::Type(CacheIdx));
|
2015-05-21 07:43:16 -04:00
|
|
|
if (NewCollection->LoadFromFile(Filename, bUseSCC))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
AddCollection(NewCollection, ECollectionShareType::Type(CacheIdx));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogCollectionManager, Warning, TEXT("Failed to load collection file %s"), *Filename);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
UE_LOG(LogCollectionManager, Log, TEXT( "Loaded %d collections in %0.6f seconds" ), CachedCollections.Num() - PrevNumCollections, FPlatformTime::Seconds() - LoadStartTime);
|
2015-05-29 13:15:23 -04:00
|
|
|
|
|
|
|
|
RebuildCachedObjects();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FCollectionManager::RebuildCachedObjects()
|
|
|
|
|
{
|
|
|
|
|
const double LoadStartTime = FPlatformTime::Seconds();
|
|
|
|
|
|
|
|
|
|
CachedObjects.Empty();
|
|
|
|
|
|
|
|
|
|
for (const auto& CachedCollection : CachedCollections)
|
|
|
|
|
{
|
|
|
|
|
const FCollectionNameType& CollectionKey = CachedCollection.Key;
|
|
|
|
|
const TSharedRef<FCollection>& Collection = CachedCollection.Value;
|
|
|
|
|
|
|
|
|
|
TArray<FName> ObjectsInCollection;
|
|
|
|
|
Collection->GetObjectsInCollection(ObjectsInCollection);
|
|
|
|
|
|
|
|
|
|
for (const FName& ObjectPath : ObjectsInCollection)
|
|
|
|
|
{
|
|
|
|
|
auto& ObjectCollections = CachedObjects.FindOrAdd(ObjectPath);
|
|
|
|
|
ObjectCollections.AddUnique(CollectionKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogCollectionManager, Log, TEXT( "Rebuilt the cache for %d objects in %0.6f seconds" ), CachedObjects.Num(), FPlatformTime::Seconds() - LoadStartTime);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::ShouldUseSCC(ECollectionShareType::Type ShareType) const
|
|
|
|
|
{
|
|
|
|
|
return ShareType != ECollectionShareType::CST_Local && ShareType != ECollectionShareType::CST_System;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
bool FCollectionManager::AddCollection(const TSharedRef<FCollection>& CollectionRef, ECollectionShareType::Type ShareType)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
const FCollectionNameType CollectionKey(CollectionRef->GetCollectionName(), ShareType);
|
|
|
|
|
if (CachedCollections.Contains(CollectionKey))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2015-05-21 07:43:16 -04:00
|
|
|
UE_LOG(LogCollectionManager, Warning, TEXT("Failed to add collection '%s' because it already exists."), *CollectionRef->GetCollectionName().ToString());
|
|
|
|
|
return false;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:43:16 -04:00
|
|
|
CachedCollections.Add(CollectionKey, CollectionRef);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FCollectionManager::RemoveCollection(const TSharedRef<FCollection>& CollectionRef, ECollectionShareType::Type ShareType)
|
|
|
|
|
{
|
|
|
|
|
if (!ensure(ShareType < ECollectionShareType::CST_All))
|
|
|
|
|
{
|
|
|
|
|
// Bad share type
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FCollectionNameType CollectionKey(CollectionRef->GetCollectionName(), ShareType);
|
|
|
|
|
return CachedCollections.Remove(CollectionKey) > 0;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|