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 ;
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : GetCollections ( TArray < FCollectionNameType > & OutCollections ) const
{
OutCollections . Reserve ( CachedCollections . Num ( ) ) ;
for ( const auto & CachedCollection : CachedCollections )
{
const FCollectionNameType & CollectionKey = CachedCollection . Key ;
OutCollections . Add ( CollectionKey ) ;
}
}
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-06-19 07:33:02 -04:00
CollectionNames . AddUnique ( CollectionKey . Name ) ;
2014-03-14 14:13:41 -04:00
}
}
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : GetRootCollections ( TArray < FCollectionNameType > & OutCollections ) const
{
OutCollections . Reserve ( CachedCollections . Num ( ) ) ;
for ( const auto & CachedCollection : CachedCollections )
{
const FCollectionNameType & CollectionKey = CachedCollection . Key ;
const TSharedRef < FCollection > & Collection = CachedCollection . Value ;
// A root collection either has no parent GUID, or a parent GUID that cannot currently be found - the check below handles both
if ( ! CachedCollectionNamesFromGuids . Contains ( Collection - > GetParentCollectionGuid ( ) ) )
{
OutCollections . Add ( CollectionKey ) ;
}
}
}
void FCollectionManager : : GetRootCollectionNames ( ECollectionShareType : : Type ShareType , TArray < FName > & CollectionNames ) const
{
for ( const auto & CachedCollection : CachedCollections )
{
const FCollectionNameType & CollectionKey = CachedCollection . Key ;
const TSharedRef < FCollection > & Collection = CachedCollection . Value ;
if ( ShareType = = ECollectionShareType : : CST_All | | ShareType = = CollectionKey . Type )
{
// A root collection either has no parent GUID, or a parent GUID that cannot currently be found - the check below handles both
if ( ! CachedCollectionNamesFromGuids . Contains ( Collection - > GetParentCollectionGuid ( ) ) )
{
CollectionNames . AddUnique ( CollectionKey . Name ) ;
}
}
}
}
void FCollectionManager : : GetChildCollections ( FName CollectionName , ECollectionShareType : : Type ShareType , TArray < FCollectionNameType > & OutCollections ) const
{
auto GetChildCollectionsInternal = [ this , & OutCollections ] ( const FCollectionNameType & InCollectionKey )
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
const auto * ChildCollectionGuids = CachedHierarchy . Find ( ( * CollectionRefPtr ) - > GetCollectionGuid ( ) ) ;
if ( ChildCollectionGuids )
{
for ( const FGuid & ChildCollectionGuid : * ChildCollectionGuids )
{
const FCollectionNameType * const ChildCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( ChildCollectionGuid ) ;
if ( ChildCollectionKeyPtr )
{
OutCollections . Add ( * ChildCollectionKeyPtr ) ;
}
}
}
}
} ;
if ( ShareType = = ECollectionShareType : : CST_All )
{
// Asked for all share types, find children in the specified collection name in any cache
for ( int32 CacheIdx = 0 ; CacheIdx < ECollectionShareType : : CST_All ; + + CacheIdx )
{
GetChildCollectionsInternal ( FCollectionNameType ( CollectionName , ECollectionShareType : : Type ( CacheIdx ) ) ) ;
}
}
else
{
GetChildCollectionsInternal ( FCollectionNameType ( CollectionName , ShareType ) ) ;
}
}
void FCollectionManager : : GetChildCollectionNames ( FName CollectionName , ECollectionShareType : : Type ShareType , ECollectionShareType : : Type ChildShareType , TArray < FName > & CollectionNames ) const
{
auto GetChildCollectionsInternal = [ this , & ChildShareType , & CollectionNames ] ( const FCollectionNameType & InCollectionKey )
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
const auto * ChildCollectionGuids = CachedHierarchy . Find ( ( * CollectionRefPtr ) - > GetCollectionGuid ( ) ) ;
if ( ChildCollectionGuids )
{
for ( const FGuid & ChildCollectionGuid : * ChildCollectionGuids )
{
const FCollectionNameType * const ChildCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( ChildCollectionGuid ) ;
if ( ChildCollectionKeyPtr & & ( ChildShareType = = ECollectionShareType : : CST_All | | ChildShareType = = ChildCollectionKeyPtr - > Type ) )
{
CollectionNames . AddUnique ( ChildCollectionKeyPtr - > Name ) ;
}
}
}
}
} ;
if ( ShareType = = ECollectionShareType : : CST_All )
{
// Asked for all share types, find children in the specified collection name in any cache
for ( int32 CacheIdx = 0 ; CacheIdx < ECollectionShareType : : CST_All ; + + CacheIdx )
{
GetChildCollectionsInternal ( FCollectionNameType ( CollectionName , ECollectionShareType : : Type ( CacheIdx ) ) ) ;
}
}
else
{
GetChildCollectionsInternal ( FCollectionNameType ( CollectionName , ShareType ) ) ;
}
}
2015-07-01 11:36:19 -04:00
TOptional < FCollectionNameType > FCollectionManager : : GetParentCollection ( FName CollectionName , ECollectionShareType : : Type ShareType ) const
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( FCollectionNameType ( CollectionName , ShareType ) ) ;
if ( CollectionRefPtr )
{
const FCollectionNameType * const ParentCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( ( * CollectionRefPtr ) - > GetParentCollectionGuid ( ) ) ;
if ( ParentCollectionKeyPtr )
{
return * ParentCollectionKeyPtr ;
}
}
return TOptional < FCollectionNameType > ( ) ;
}
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
}
}
2015-06-19 07:33:02 -04:00
bool FCollectionManager : : GetAssetsInCollection ( FName CollectionName , ECollectionShareType : : Type ShareType , TArray < FName > & AssetsPaths , ECollectionRecursionFlags : : Flags RecursionMode ) const
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
bool bFoundAssets = false ;
auto GetAssetsInCollectionWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
2015-05-21 07:43:16 -04:00
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
( * CollectionRefPtr ) - > GetAssetsInCollection ( AssetsPaths ) ;
2015-06-19 07:33:02 -04:00
bFoundAssets = true ;
2015-05-21 07:43:16 -04:00
}
2015-06-19 07:33:02 -04:00
return ERecursiveWorkerFlowControl : : Continue ;
2015-05-21 07:43:16 -04:00
} ;
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
for ( int32 CacheIdx = 0 ; CacheIdx < ECollectionShareType : : CST_All ; + + CacheIdx )
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ECollectionShareType : : Type ( CacheIdx ) ) , RecursionMode , GetAssetsInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
}
else
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ShareType ) , RecursionMode , GetAssetsInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
return bFoundAssets ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
bool FCollectionManager : : GetClassesInCollection ( FName CollectionName , ECollectionShareType : : Type ShareType , TArray < FName > & ClassPaths , ECollectionRecursionFlags : : Flags RecursionMode ) const
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
bool bFoundClasses = false ;
auto GetClassesInCollectionWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
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 ) ;
2015-06-19 07:33:02 -04:00
bFoundClasses = true ;
2015-05-21 07:43:16 -04:00
}
2015-06-19 07:33:02 -04:00
return ERecursiveWorkerFlowControl : : Continue ;
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 ( ShareType = = ECollectionShareType : : CST_All )
{
// Asked for all share types, find classes in the specified collection name in any cache
2014-03-14 14:13:41 -04:00
for ( int32 CacheIdx = 0 ; CacheIdx < ECollectionShareType : : CST_All ; + + CacheIdx )
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ECollectionShareType : : Type ( CacheIdx ) ) , RecursionMode , GetClassesInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
}
else
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ShareType ) , RecursionMode , GetClassesInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
return bFoundClasses ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
bool FCollectionManager : : GetObjectsInCollection ( FName CollectionName , ECollectionShareType : : Type ShareType , TArray < FName > & ObjectPaths , ECollectionRecursionFlags : : Flags RecursionMode ) const
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
bool bFoundObjects = false ;
auto GetObjectsInCollectionWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
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 ) ;
2015-06-19 07:33:02 -04:00
bFoundObjects = true ;
2015-05-21 07:43:16 -04:00
}
2015-06-19 07:33:02 -04:00
return ERecursiveWorkerFlowControl : : Continue ;
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 ( ShareType = = ECollectionShareType : : CST_All )
{
2015-06-19 07:33:02 -04:00
// Asked for all share types, find classes in the specified collection name in any cache
2014-03-14 14:13:41 -04:00
for ( int32 CacheIdx = 0 ; CacheIdx < ECollectionShareType : : CST_All ; + + CacheIdx )
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ECollectionShareType : : Type ( CacheIdx ) ) , RecursionMode , GetObjectsInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
}
else
{
2015-06-19 07:33:02 -04:00
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ShareType ) , RecursionMode , GetObjectsInCollectionWorker ) ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
return bFoundObjects ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : GetCollectionsContainingObject ( FName ObjectPath , ECollectionShareType : : Type ShareType , TArray < FName > & OutCollectionNames , ECollectionRecursionFlags : : Flags RecursionMode ) const
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
const auto * ObjectCollectionInfosPtr = CachedObjects . Find ( ObjectPath ) ;
if ( ObjectCollectionInfosPtr )
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
for ( const FObjectCollectionInfo & ObjectCollectionInfo : * ObjectCollectionInfosPtr )
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
if ( ( ShareType = = ECollectionShareType : : CST_All | | ShareType = = ObjectCollectionInfo . CollectionKey . Type ) & & ( RecursionMode & ObjectCollectionInfo . Reason ) ! = 0 )
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
OutCollectionNames . Add ( ObjectCollectionInfo . CollectionKey . Name ) ;
2015-05-29 13:15:23 -04:00
}
}
}
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : GetCollectionsContainingObject ( FName ObjectPath , TArray < FCollectionNameType > & OutCollections , ECollectionRecursionFlags : : Flags RecursionMode ) const
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
const auto * ObjectCollectionInfosPtr = CachedObjects . Find ( ObjectPath ) ;
if ( ObjectCollectionInfosPtr )
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
OutCollections . Reserve ( OutCollections . Num ( ) + ObjectCollectionInfosPtr - > Num ( ) ) ;
for ( const FObjectCollectionInfo & ObjectCollectionInfo : * ObjectCollectionInfosPtr )
{
if ( ( RecursionMode & ObjectCollectionInfo . Reason ) ! = 0 )
{
OutCollections . Add ( ObjectCollectionInfo . CollectionKey ) ;
}
}
2015-05-29 13:15:23 -04:00
}
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : GetCollectionsContainingObjects ( const TArray < FName > & ObjectPaths , TMap < FCollectionNameType , TArray < FName > > & OutCollectionsAndMatchedObjects , ECollectionRecursionFlags : : Flags RecursionMode ) const
2015-05-29 13:15:23 -04:00
{
for ( const FName & ObjectPath : ObjectPaths )
{
2015-06-19 07:33:02 -04:00
const auto * ObjectCollectionInfosPtr = CachedObjects . Find ( ObjectPath ) ;
if ( ObjectCollectionInfosPtr )
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
for ( const FObjectCollectionInfo & ObjectCollectionInfo : * ObjectCollectionInfosPtr )
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
if ( ( RecursionMode & ObjectCollectionInfo . Reason ) ! = 0 )
{
TArray < FName > & MatchedObjects = OutCollectionsAndMatchedObjects . FindOrAdd ( ObjectCollectionInfo . CollectionKey ) ;
MatchedObjects . Add ( ObjectPath ) ;
}
2015-05-29 13:15:23 -04:00
}
2014-03-14 14:13:41 -04:00
}
}
}
2015-06-19 07:33:02 -04:00
FString FCollectionManager : : GetCollectionsStringForObject ( FName ObjectPath , ECollectionShareType : : Type ShareType , ECollectionRecursionFlags : : Flags RecursionMode ) const
2015-05-21 09:23:51 -04:00
{
2015-06-19 07:33:02 -04:00
const auto * ObjectCollectionInfosPtr = CachedObjects . Find ( ObjectPath ) ;
if ( ObjectCollectionInfosPtr )
2015-05-29 13:15:23 -04:00
{
TArray < FString > CollectionNameStrings ;
2015-05-21 09:23:51 -04:00
2015-07-01 10:25:19 -04:00
TArray < FString > CollectionPathStrings ;
auto GetCollectionsStringForObjectWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
{
CollectionPathStrings . Insert ( InCollectionKey . Name . ToString ( ) , 0 ) ;
return ERecursiveWorkerFlowControl : : Continue ;
} ;
2015-06-19 07:33:02 -04:00
for ( const FObjectCollectionInfo & ObjectCollectionInfo : * ObjectCollectionInfosPtr )
2015-05-21 09:23:51 -04:00
{
2015-06-19 07:33:02 -04:00
if ( ( ShareType = = ECollectionShareType : : CST_All | | ShareType = = ObjectCollectionInfo . CollectionKey . Type ) & & ( RecursionMode & ObjectCollectionInfo . Reason ) ! = 0 )
2015-05-29 13:15:23 -04:00
{
2015-07-01 10:25:19 -04:00
CollectionPathStrings . Reset ( ) ;
RecursionHelper_DoWork ( ObjectCollectionInfo . CollectionKey , ECollectionRecursionFlags : : SelfAndParents , GetCollectionsStringForObjectWorker ) ;
CollectionNameStrings . Add ( FString : : Join ( CollectionPathStrings , TEXT ( " / " ) ) ) ;
2015-05-29 13:15:23 -04:00
}
}
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
}
2015-07-02 12:20:22 -04:00
bool FCollectionManager : : IsValidCollectionName ( const FString & CollectionName , ECollectionShareType : : Type ShareType ) const
{
// Make sure we are not creating an FName that is too large
if ( CollectionName . Len ( ) > NAME_SIZE )
{
LastError = LOCTEXT ( " Error_CollectionNameTooLong " , " This collection name is too long. Please choose a shorter name. " ) ;
return false ;
}
const FName CollectionNameFinal = * CollectionName ;
// Make sure the we actually have a new name set
if ( CollectionNameFinal . IsNone ( ) )
{
LastError = LOCTEXT ( " Error_CollectionNameEmptyOrNone " , " This collection name cannot be empty or 'None'. " ) ;
return false ;
}
// Make sure the new name only contains valid characters
if ( ! CollectionNameFinal . IsValidXName ( INVALID_OBJECTNAME_CHARACTERS INVALID_LONGPACKAGE_CHARACTERS , & LastError ) )
{
return false ;
}
// Make sure we're not duplicating an existing collection name
if ( CollectionExists ( CollectionNameFinal , ShareType ) )
{
LastError = FText : : Format ( LOCTEXT ( " Error_CollectionAlreadyExists " , " A collection already exists with the name '{0}'. " ) , FText : : FromName ( CollectionNameFinal ) ) ;
return false ;
}
return true ;
}
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
2015-06-19 07:33:02 -04:00
const bool bUseSCC = ShouldUseSCC ( ShareType ) ;
const FString CollectionFilename = GetCollectionFilename ( CollectionName , ShareType ) ;
2014-03-14 14:13:41 -04:00
2015-06-19 07:33:02 -04:00
TSharedRef < FCollection > NewCollection = MakeShareable ( new FCollection ( CollectionFilename , bUseSCC ) ) ;
2015-05-21 07:43:16 -04:00
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 ;
}
2015-06-19 07:33:02 -04:00
const FCollectionNameType OriginalCollectionKey ( CurrentCollectionName , CurrentShareType ) ;
const FCollectionNameType NewCollectionKey ( NewCollectionName , NewShareType ) ;
TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( OriginalCollectionKey ) ;
if ( ! CollectionRefPtr )
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
// The collection doesn't exist
LastError = LOCTEXT ( " Error_DoesntExist " , " The collection doesn't exist. " ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2015-06-19 07:33:02 -04:00
// Add the new collection
TSharedPtr < FCollection > NewCollection ;
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
const bool bUseSCC = ShouldUseSCC ( NewShareType ) ;
const FString NewCollectionFilename = GetCollectionFilename ( NewCollectionName , NewShareType ) ;
2014-03-14 14:13:41 -04:00
2015-06-19 07:33:02 -04:00
// Create an exact copy of the collection using its new path - this will preserve its GUID and avoid losing hierarchy data
NewCollection = ( * CollectionRefPtr ) - > Clone ( NewCollectionFilename , bUseSCC , ECollectionCloneMode : : Exact ) ;
if ( ! AddCollection ( NewCollection . ToSharedRef ( ) , NewShareType ) )
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
// Failed to add the collection, it already exists
LastError = LOCTEXT ( " Error_AlreadyExists " , " The collection already exists. " ) ;
return false ;
}
if ( ! NewCollection - > Save ( LastError ) )
{
// Collection failed to save, remove it from the cache
RemoveCollection ( NewCollection . ToSharedRef ( ) , NewShareType ) ;
// Restore the original GUID mapping since AddCollection replaced it
CachedCollectionNamesFromGuids . Add ( ( * CollectionRefPtr ) - > GetCollectionGuid ( ) , OriginalCollectionKey ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
}
2015-06-19 07:33:02 -04:00
// Remove the old collection
2014-03-14 14:13:41 -04:00
{
2015-06-19 07:33:02 -04:00
if ( ( * CollectionRefPtr ) - > DeleteSourceFile ( LastError ) )
{
RemoveCollection ( * CollectionRefPtr , CurrentShareType ) ;
// Re-add the new GUID mapping since RemoveCollection removed it
CachedCollectionNamesFromGuids . Add ( NewCollection - > GetCollectionGuid ( ) , NewCollectionKey ) ;
}
else
{
// Failed to remove the old collection, so remove the collection we created.
NewCollection - > DeleteSourceFile ( LastError ) ;
RemoveCollection ( NewCollection . ToSharedRef ( ) , NewShareType ) ;
// Restore the original GUID mapping since RemoveCollection removed it
CachedCollectionNamesFromGuids . Add ( ( * CollectionRefPtr ) - > GetCollectionGuid ( ) , OriginalCollectionKey ) ;
return false ;
}
2014-03-14 14:13:41 -04:00
}
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
CollectionRenamedEvent . Broadcast ( OriginalCollectionKey , NewCollectionKey ) ;
2014-03-14 14:13:41 -04:00
return true ;
}
2015-06-19 07:33:02 -04:00
bool FCollectionManager : : ReparentCollection ( FName CollectionName , ECollectionShareType : : Type ShareType , FName ParentCollectionName , ECollectionShareType : : Type ParentShareType )
{
if ( ! ensure ( ShareType < ECollectionShareType : : CST_All ) | | ( ! ParentCollectionName . IsNone ( ) & & ! ensure ( ParentShareType < ECollectionShareType : : CST_All ) ) )
{
// Bad share type
LastError = LOCTEXT ( " Error_Internal " , " There was an internal error. " ) ;
return false ;
}
const FCollectionNameType CollectionKey ( CollectionName , ShareType ) ;
TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( CollectionKey ) ;
if ( ! CollectionRefPtr )
{
// The collection doesn't exist
LastError = LOCTEXT ( " Error_DoesntExist " , " The collection doesn't exist. " ) ;
return false ;
}
const FGuid OldParentGuid = ( * CollectionRefPtr ) - > GetParentCollectionGuid ( ) ;
FGuid NewParentGuid ;
TOptional < FCollectionNameType > OldParentCollectionKey ;
TOptional < FCollectionNameType > NewParentCollectionKey ;
if ( ! ParentCollectionName . IsNone ( ) )
{
// Find and set the new parent GUID
NewParentCollectionKey = FCollectionNameType ( ParentCollectionName , ParentShareType ) ;
TSharedRef < FCollection > * const ParentCollectionRefPtr = CachedCollections . Find ( NewParentCollectionKey . GetValue ( ) ) ;
if ( ! ParentCollectionRefPtr )
{
// The collection doesn't exist
LastError = LOCTEXT ( " Error_DoesntExist " , " The collection doesn't exist. " ) ;
return false ;
}
// Does the parent collection need saving in order to have a stable GUID?
if ( ( * ParentCollectionRefPtr ) - > GetCollectionVersion ( ) < ECollectionVersion : : AddedCollectionGuid )
{
// Try and re-save the parent collection now
if ( ! ( * ParentCollectionRefPtr ) - > Save ( LastError ) )
{
return false ;
}
}
if ( ! IsValidParentCollection ( CollectionName , ShareType , ParentCollectionName , ParentShareType ) )
{
// IsValidParentCollection fills in LastError itself
return false ;
}
NewParentGuid = ( * ParentCollectionRefPtr ) - > GetCollectionGuid ( ) ;
}
// Anything changed?
if ( OldParentGuid = = NewParentGuid )
{
return true ;
}
( * CollectionRefPtr ) - > SetParentCollectionGuid ( NewParentGuid ) ;
// Try and save with the new parent GUID
if ( ! ( * CollectionRefPtr ) - > Save ( LastError ) )
{
// Failed to save... rollback the collection to use its old parent GUID
( * CollectionRefPtr ) - > SetParentCollectionGuid ( OldParentGuid ) ;
return false ;
}
// Find the old parent so we can notify about the change
{
const FCollectionNameType * const OldParentCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( OldParentGuid ) ;
if ( OldParentCollectionKeyPtr )
{
OldParentCollectionKey = * OldParentCollectionKeyPtr ;
}
}
RebuildCachedHierarchy ( ) ;
RebuildCachedObjects ( ) ;
// Success
CollectionReparentedEvent . Broadcast ( CollectionKey , OldParentCollectionKey , NewParentCollectionKey ) ;
return true ;
}
2014-03-14 14:13:41 -04:00
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
2015-06-19 07:33:02 -04:00
RebuildCachedHierarchy ( ) ;
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-06-26 13:13:02 -04:00
if ( ( * CollectionRefPtr ) - > AddObjectToCollection ( 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 )
{
2015-06-26 13:13:02 -04:00
( * CollectionRefPtr ) - > RemoveObjectFromCollection ( ObjectPath ) ;
2015-05-21 07:43:16 -04:00
}
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 )
{
2015-06-26 13:13:02 -04:00
if ( ( * CollectionRefPtr ) - > RemoveObjectFromCollection ( ObjectPath ) )
2015-05-21 07:43:16 -04:00
{
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 )
{
2015-06-26 13:13:02 -04:00
( * CollectionRefPtr ) - > AddObjectToCollection ( RemovedAssetName ) ;
2015-05-21 07:43:16 -04:00
}
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-06-19 07:33:02 -04:00
if ( ! GetObjectsInCollection ( 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-06-19 07:33:02 -04:00
bool FCollectionManager : : IsObjectInCollection ( FName ObjectPath , FName CollectionName , ECollectionShareType : : Type ShareType , ECollectionRecursionFlags : : Flags RecursionMode ) const
2015-05-29 13:15:23 -04:00
{
if ( ! ensure ( ShareType < ECollectionShareType : : CST_All ) )
{
// Bad share type
LastError = LOCTEXT ( " Error_Internal " , " There was an internal error. " ) ;
return true ;
}
2015-06-19 07:33:02 -04:00
bool bFoundObject = false ;
auto IsObjectInCollectionWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
bFoundObject = ( * CollectionRefPtr ) - > IsObjectInCollection ( ObjectPath ) ;
}
return ( bFoundObject ) ? ERecursiveWorkerFlowControl : : Stop : ERecursiveWorkerFlowControl : : Continue ;
} ;
RecursionHelper_DoWork ( FCollectionNameType ( CollectionName , ShareType ) , RecursionMode , IsObjectInCollectionWorker ) ;
return bFoundObject ;
}
bool FCollectionManager : : IsValidParentCollection ( FName CollectionName , ECollectionShareType : : Type ShareType , FName ParentCollectionName , ECollectionShareType : : Type ParentShareType ) const
{
if ( ! ensure ( ShareType < ECollectionShareType : : CST_All ) | | ( ! ParentCollectionName . IsNone ( ) & & ! ensure ( ParentShareType < ECollectionShareType : : CST_All ) ) )
{
// Bad share type
LastError = LOCTEXT ( " Error_Internal " , " There was an internal error. " ) ;
return true ;
2015-05-29 13:15:23 -04:00
}
2015-06-19 07:33:02 -04:00
if ( ParentCollectionName . IsNone ( ) )
{
// Clearing the parent is always valid
return true ;
}
bool bValidParent = true ;
auto IsValidParentCollectionWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
{
const bool bMatchesCollectionBeingReparented = ( CollectionName = = InCollectionKey . Name & & ShareType = = InCollectionKey . Type ) ;
if ( bMatchesCollectionBeingReparented )
{
bValidParent = false ;
LastError = ( InReason = = ECollectionRecursionFlags : : Self )
? LOCTEXT ( " InvalidParent_CannotParentToSelf " , " A collection cannot be parented to itself " )
: LOCTEXT ( " InvalidParent_CannotParentToChildren " , " A collection cannot be parented to its children " ) ;
return ERecursiveWorkerFlowControl : : Stop ;
}
2015-07-01 12:12:44 -04:00
const bool bIsValidChildType = ECollectionShareType : : IsValidChildType ( InCollectionKey . Type , ShareType ) ;
if ( ! bIsValidChildType )
{
bValidParent = false ;
LastError = FText : : Format ( LOCTEXT ( " InvalidParent_InvalidChildType " , " A {0} collection cannot contain a {1} collection " ) , ECollectionShareType : : ToText ( InCollectionKey . Type ) , ECollectionShareType : : ToText ( ShareType ) ) ;
return ERecursiveWorkerFlowControl : : Stop ;
}
2015-06-19 07:33:02 -04:00
return ERecursiveWorkerFlowControl : : Continue ;
} ;
RecursionHelper_DoWork ( FCollectionNameType ( ParentCollectionName , ParentShareType ) , ECollectionRecursionFlags : : SelfAndParents , IsValidParentCollectionWorker ) ;
return bValidParent ;
2015-05-29 13:15:23 -04:00
}
2015-06-26 13:13:02 -04:00
void FCollectionManager : : HandleFixupRedirectors ( ICollectionRedirectorFollower & InRedirectorFollower )
{
const double LoadStartTime = FPlatformTime : : Seconds ( ) ;
TArray < TPair < FName , FName > > ObjectsToRename ;
// Build up the list of redirected object into rename pairs
for ( const auto & CachedObjectInfo : CachedObjects )
{
FName NewObjectPath ;
if ( InRedirectorFollower . FixupObject ( CachedObjectInfo . Key , NewObjectPath ) )
{
ObjectsToRename . Add ( TPairInitializer < FName , FName > ( CachedObjectInfo . Key , NewObjectPath ) ) ;
}
}
// Notify the rename for each redirected object
for ( const auto & ObjectToRename : ObjectsToRename )
{
HandleObjectRenamed ( ObjectToRename . Key , ObjectToRename . Value ) ;
}
UE_LOG ( LogCollectionManager , Log , TEXT ( " Fixed up redirectors for %d collections in %0.6f seconds (updated %d objects) " ) , CachedCollections . Num ( ) , FPlatformTime : : Seconds ( ) - LoadStartTime , ObjectsToRename . Num ( ) ) ;
for ( const auto & ObjectToRename : ObjectsToRename )
{
UE_LOG ( LogCollectionManager , Verbose , TEXT ( " \t Redirected '%s' to '%s' " ) , * ObjectToRename . Key . ToString ( ) , * ObjectToRename . Value . ToString ( ) ) ;
}
}
bool FCollectionManager : : HandleRedirectorDeleted ( const FName & ObjectPath )
{
bool bSavedAllCollections = true ;
FTextBuilder AllErrors ;
// We don't have a cache for on-disk objects, so we have to do this the slower way and query each collection in turn
for ( const auto & CachedCollection : CachedCollections )
{
const TSharedRef < FCollection > & Collection = CachedCollection . Value ;
if ( Collection - > IsRedirectorInCollection ( ObjectPath ) )
{
FText SaveError ;
if ( ! Collection - > Save ( SaveError ) )
{
AllErrors . AppendLine ( SaveError ) ;
bSavedAllCollections = false ;
}
}
}
if ( ! bSavedAllCollections )
{
LastError = AllErrors . ToText ( ) ;
}
return bSavedAllCollections ;
}
void FCollectionManager : : HandleObjectRenamed ( const FName & OldObjectPath , const FName & NewObjectPath )
{
// Remove the info about the collections that the old object path is within - we'll add this info back in under the new object path shortly
TArray < FObjectCollectionInfo > OldObjectCollectionInfos ;
if ( ! CachedObjects . RemoveAndCopyValue ( OldObjectPath , OldObjectCollectionInfos ) )
{
return ;
}
// Replace this object reference in all collections that use it, and update our object cache
auto & NewObjectCollectionInfos = CachedObjects . FindOrAdd ( NewObjectPath ) ;
for ( const FObjectCollectionInfo & OldObjectCollectionInfo : OldObjectCollectionInfos )
{
if ( ( OldObjectCollectionInfo . Reason & ECollectionRecursionFlags : : Self ) ! = 0 )
{
// The old object is contained directly within this collection (rather than coming from a parent or child collection), so update the object reference
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( OldObjectCollectionInfo . CollectionKey ) ;
if ( CollectionRefPtr )
{
( * CollectionRefPtr ) - > RemoveObjectFromCollection ( OldObjectPath ) ;
( * CollectionRefPtr ) - > AddObjectToCollection ( NewObjectPath ) ;
}
}
// Merge the collection references for the old object with any collection references that already exist for the new object
FObjectCollectionInfo * ObjectInfoPtr = NewObjectCollectionInfos . FindByPredicate ( [ & ] ( const FObjectCollectionInfo & InCollectionInfo ) { return InCollectionInfo . CollectionKey = = OldObjectCollectionInfo . CollectionKey ; } ) ;
if ( ObjectInfoPtr )
{
ObjectInfoPtr - > Reason | = OldObjectCollectionInfo . Reason ;
}
else
{
NewObjectCollectionInfos . Add ( OldObjectCollectionInfo ) ;
}
}
}
void FCollectionManager : : HandleObjectDeleted ( const FName & ObjectPath )
{
// Remove the info about the collections that the old object path is within
TArray < FObjectCollectionInfo > ObjectCollectionInfos ;
if ( ! CachedObjects . RemoveAndCopyValue ( ObjectPath , ObjectCollectionInfos ) )
{
return ;
}
// Remove this object reference from all collections that use it
for ( const FObjectCollectionInfo & ObjectCollectionInfo : ObjectCollectionInfos )
{
if ( ( ObjectCollectionInfo . Reason & ECollectionRecursionFlags : : Self ) ! = 0 )
{
// The object is contained directly within this collection (rather than coming from a parent or child collection), so remove the object reference
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( ObjectCollectionInfo . CollectionKey ) ;
if ( CollectionRefPtr )
{
( * CollectionRefPtr ) - > RemoveObjectFromCollection ( ObjectPath ) ;
}
}
}
}
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
const bool bUseSCC = ShouldUseSCC ( ECollectionShareType : : Type ( CacheIdx ) ) ;
2015-06-19 07:33:02 -04:00
FText LoadErrorText ;
TSharedRef < FCollection > NewCollection = MakeShareable ( new FCollection ( Filename , bUseSCC ) ) ;
if ( NewCollection - > Load ( LoadErrorText ) )
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
{
2015-06-19 07:33:02 -04:00
UE_LOG ( LogCollectionManager , Warning , TEXT ( " %s " ) , * LoadErrorText . ToString ( ) ) ;
2014-03-14 14:13:41 -04:00
}
}
}
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
2015-06-19 07:33:02 -04:00
RebuildCachedHierarchy ( ) ;
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 ;
2015-06-26 13:13:02 -04:00
Collection - > GetObjectsInCollection ( ObjectsInCollection ) ;
2015-05-29 13:15:23 -04:00
2015-06-19 07:33:02 -04:00
if ( ObjectsInCollection . Num ( ) > 0 )
2015-05-29 13:15:23 -04:00
{
2015-06-19 07:33:02 -04:00
auto RebuildCachedObjectsWorker = [ & ] ( const FCollectionNameType & InCollectionKey , ECollectionRecursionFlags : : Flag InReason ) - > ERecursiveWorkerFlowControl
{
// The worker reason will tell us why this collection is being processed (eg, because it is a parent of the collection we told it to DoWork on),
// however, the reason this object exists in that parent collection is because a child collection contains it, and this is the reason we need
// to put into the FObjectCollectionInfo, since that's what we'll test against later when we do the "do my children contain this object"? test
// That's why we flip the reason logic here...
ECollectionRecursionFlags : : Flag ReasonObjectInCollection = InReason ;
switch ( InReason )
{
case ECollectionRecursionFlags : : Parents :
ReasonObjectInCollection = ECollectionRecursionFlags : : Children ;
break ;
case ECollectionRecursionFlags : : Children :
ReasonObjectInCollection = ECollectionRecursionFlags : : Parents ;
break ;
default :
break ;
}
for ( const FName & ObjectPath : ObjectsInCollection )
{
auto & ObjectCollectionInfos = CachedObjects . FindOrAdd ( ObjectPath ) ;
FObjectCollectionInfo * ObjectInfoPtr = ObjectCollectionInfos . FindByPredicate ( [ & ] ( const FObjectCollectionInfo & InCollectionInfo ) { return InCollectionInfo . CollectionKey = = InCollectionKey ; } ) ;
if ( ObjectInfoPtr )
{
ObjectInfoPtr - > Reason | = ReasonObjectInCollection ;
}
else
{
ObjectCollectionInfos . Add ( FObjectCollectionInfo ( InCollectionKey , ReasonObjectInCollection ) ) ;
}
}
return ERecursiveWorkerFlowControl : : Continue ;
} ;
// Recursively process all collections so that they know they contain these objects (and why!)
RecursionHelper_DoWork ( CollectionKey , ECollectionRecursionFlags : : All , RebuildCachedObjectsWorker ) ;
2015-05-29 13:15:23 -04:00
}
}
2015-06-19 07:33:02 -04:00
UE_LOG ( LogCollectionManager , Log , TEXT ( " Rebuilt the object cache for %d collections in %0.6f seconds (found %d objects) " ) , CachedCollections . Num ( ) , FPlatformTime : : Seconds ( ) - LoadStartTime , CachedObjects . Num ( ) ) ;
}
void FCollectionManager : : RebuildCachedHierarchy ( )
{
const double LoadStartTime = FPlatformTime : : Seconds ( ) ;
CachedHierarchy . Empty ( ) ;
for ( const auto & CachedCollection : CachedCollections )
{
const FCollectionNameType & CollectionKey = CachedCollection . Key ;
const TSharedRef < FCollection > & Collection = CachedCollection . Value ;
// Make sure this is a known parent GUID before adding it to the map
const FGuid & ParentCollectionGuid = Collection - > GetParentCollectionGuid ( ) ;
if ( CachedCollectionNamesFromGuids . Contains ( ParentCollectionGuid ) )
{
auto & CollectionChildren = CachedHierarchy . FindOrAdd ( ParentCollectionGuid ) ;
CollectionChildren . AddUnique ( Collection - > GetCollectionGuid ( ) ) ;
}
}
UE_LOG ( LogCollectionManager , Log , TEXT ( " Rebuilt the hierarchy cache for %d collections in %0.6f seconds " ) , CachedCollections . 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-06-19 07:33:02 -04:00
FString FCollectionManager : : GetCollectionFilename ( const FName & InCollectionName , const ECollectionShareType : : Type InCollectionShareType ) const
{
FString CollectionFilename = CollectionFolders [ InCollectionShareType ] / InCollectionName . ToString ( ) + TEXT ( " . " ) + CollectionExtension ;
FPaths : : NormalizeFilename ( CollectionFilename ) ;
return CollectionFilename ;
}
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 ) ;
2015-06-19 07:33:02 -04:00
CachedCollectionNamesFromGuids . Add ( CollectionRef - > GetCollectionGuid ( ) , CollectionKey ) ;
2015-05-21 07:43:16 -04:00
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 ) ;
2015-06-19 07:33:02 -04:00
CachedCollectionNamesFromGuids . Remove ( CollectionRef - > GetCollectionGuid ( ) ) ;
2015-05-21 07:43:16 -04:00
return CachedCollections . Remove ( CollectionKey ) > 0 ;
2014-03-14 14:13:41 -04:00
}
2015-06-19 07:33:02 -04:00
void FCollectionManager : : RecursionHelper_DoWork ( const FCollectionNameType & InCollectionKey , const ECollectionRecursionFlags : : Flags InRecursionMode , const FRecursiveWorkerFunc & InWorkerFunc ) const
{
if ( ( InRecursionMode & ECollectionRecursionFlags : : Self ) & & InWorkerFunc ( InCollectionKey , ECollectionRecursionFlags : : Self ) = = ERecursiveWorkerFlowControl : : Stop )
{
return ;
}
if ( ( InRecursionMode & ECollectionRecursionFlags : : Parents ) & & RecursionHelper_DoWorkOnParents ( InCollectionKey , InWorkerFunc ) = = ERecursiveWorkerFlowControl : : Stop )
{
return ;
}
if ( ( InRecursionMode & ECollectionRecursionFlags : : Children ) & & RecursionHelper_DoWorkOnChildren ( InCollectionKey , InWorkerFunc ) = = ERecursiveWorkerFlowControl : : Stop )
{
return ;
}
}
FCollectionManager : : ERecursiveWorkerFlowControl FCollectionManager : : RecursionHelper_DoWorkOnParents ( const FCollectionNameType & InCollectionKey , const FRecursiveWorkerFunc & InWorkerFunc ) const
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
const FCollectionNameType * const ParentCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( ( * CollectionRefPtr ) - > GetParentCollectionGuid ( ) ) ;
if ( ParentCollectionKeyPtr )
{
if ( InWorkerFunc ( * ParentCollectionKeyPtr , ECollectionRecursionFlags : : Parents ) = = ERecursiveWorkerFlowControl : : Stop | | RecursionHelper_DoWorkOnParents ( * ParentCollectionKeyPtr , InWorkerFunc ) = = ERecursiveWorkerFlowControl : : Stop )
{
return ERecursiveWorkerFlowControl : : Stop ;
}
}
}
return ERecursiveWorkerFlowControl : : Continue ;
}
FCollectionManager : : ERecursiveWorkerFlowControl FCollectionManager : : RecursionHelper_DoWorkOnChildren ( const FCollectionNameType & InCollectionKey , const FRecursiveWorkerFunc & InWorkerFunc ) const
{
const TSharedRef < FCollection > * const CollectionRefPtr = CachedCollections . Find ( InCollectionKey ) ;
if ( CollectionRefPtr )
{
const TArray < FGuid > * const ChildCollectionGuids = CachedHierarchy . Find ( ( * CollectionRefPtr ) - > GetCollectionGuid ( ) ) ;
if ( ChildCollectionGuids )
{
for ( const FGuid & ChildCollectionGuid : * ChildCollectionGuids )
{
const FCollectionNameType * const ChildCollectionKeyPtr = CachedCollectionNamesFromGuids . Find ( ChildCollectionGuid ) ;
if ( ChildCollectionKeyPtr )
{
if ( InWorkerFunc ( * ChildCollectionKeyPtr , ECollectionRecursionFlags : : Children ) = = ERecursiveWorkerFlowControl : : Stop | | RecursionHelper_DoWorkOnChildren ( * ChildCollectionKeyPtr , InWorkerFunc ) = = ERecursiveWorkerFlowControl : : Stop )
{
return ERecursiveWorkerFlowControl : : Stop ;
}
}
}
}
}
return ERecursiveWorkerFlowControl : : Continue ;
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE