2020-12-14 15:48:27 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundUObjectRegistry.h"
# include "Algo/Copy.h"
2021-06-16 11:21:13 -04:00
# include "AssetData.h"
2020-12-14 15:48:27 -04:00
# include "AssetRegistry/AssetRegistryModule.h"
2020-12-26 19:37:43 -04:00
# include "Async/Async.h"
2021-01-13 10:48:59 -04:00
# include "Async/TaskGraphInterfaces.h"
2020-12-14 15:48:27 -04:00
# include "CoreMinimal.h"
2021-06-16 11:21:13 -04:00
# include "Engine/AssetManager.h"
# include "Metasound.h"
# include "MetasoundAssetBase.h"
2021-06-23 20:08:21 -04:00
# include "MetasoundFrontendArchetypeRegistry.h"
2021-06-16 11:21:13 -04:00
# include "MetasoundFrontendRegistries.h"
# include "MetasoundFrontendTransform.h"
2021-08-09 15:13:40 -04:00
# include "MetasoundSettings.h"
2021-06-16 11:21:13 -04:00
# include "MetasoundSource.h"
2021-08-11 15:22:01 -04:00
# include "MetasoundTrace.h"
2020-12-14 15:48:27 -04:00
# include "UObject/Object.h"
2021-06-16 11:21:13 -04:00
namespace Metasound
{
2020-12-14 15:48:27 -04:00
class FMetasoundUObjectRegistry : public IMetasoundUObjectRegistry
{
public :
2021-12-10 19:13:22 -05:00
FMetasoundUObjectRegistry ( )
{
// Set default version to use base UMetaSound class implementation
FMetasoundFrontendVersion DefaultVersion ;
using FRegistryEntryType = TMetasoundUObjectRegistryEntry < UMetaSound > ;
RegisterUClassInterface ( MakeUnique < FRegistryEntryType > ( DefaultVersion ) ) ;
}
2021-11-22 15:55:50 -05:00
void RegisterUClassInterface ( TUniquePtr < IMetasoundUObjectRegistryEntry > & & InEntry ) override
2020-12-14 15:48:27 -04:00
{
if ( InEntry . IsValid ( ) )
{
2021-11-22 15:55:50 -05:00
Frontend : : FInterfaceRegistryKey Key = Frontend : : GetInterfaceRegistryKey ( InEntry - > GetInterfaceVersion ( ) ) ;
2020-12-14 15:48:27 -04:00
2021-11-22 15:55:50 -05:00
EntriesByInterface . Add ( Key , InEntry . Get ( ) ) ;
EntriesByName . Add ( InEntry - > GetInterfaceVersion ( ) . Name , InEntry . Get ( ) ) ;
2020-12-14 15:48:27 -04:00
Entries . Add ( InEntry . Get ( ) ) ;
Storage . Add ( MoveTemp ( InEntry ) ) ;
}
}
2021-11-22 15:55:50 -05:00
TArray < const IMetasoundUObjectRegistryEntry * > FindInterfaceEntriesByName ( FName InName ) const override
{
TArray < const IMetasoundUObjectRegistryEntry * > EntriesWithName ;
EntriesByName . MultiFind ( InName , EntriesWithName ) ;
return EntriesWithName ;
}
TArray < UClass * > FindSupportedInterfaceClasses ( const FMetasoundFrontendVersion & InInterfaceVersion ) const override
2020-12-14 15:48:27 -04:00
{
TArray < UClass * > Classes ;
2021-11-22 15:55:50 -05:00
TArray < const IMetasoundUObjectRegistryEntry * > EntriesForInterface ;
EntriesByInterface . MultiFind ( Frontend : : GetInterfaceRegistryKey ( InInterfaceVersion ) , EntriesForInterface ) ;
2020-12-14 15:48:27 -04:00
2021-11-22 15:55:50 -05:00
for ( const IMetasoundUObjectRegistryEntry * Entry : EntriesForInterface )
2020-12-14 15:48:27 -04:00
{
if ( nullptr ! = Entry )
{
if ( UClass * Class = Entry - > GetUClass ( ) )
{
Classes . Add ( Class ) ;
}
}
}
return Classes ;
}
2021-06-23 20:08:21 -04:00
UObject * NewObject ( UClass * InClass , const FMetasoundFrontendDocument & InDocument , const FString & InPath ) const override
2020-12-14 15:48:27 -04:00
{
2021-11-22 15:55:50 -05:00
TArray < const IMetasoundUObjectRegistryEntry * > AllInterfaceEntries ;
2021-12-10 19:13:22 -05:00
for ( const FMetasoundFrontendVersion & InterfaceVersion : InDocument . InterfaceVersions )
2021-11-22 15:55:50 -05:00
{
TArray < const IMetasoundUObjectRegistryEntry * > EntriesForInterface ;
EntriesByInterface . MultiFind ( Frontend : : GetInterfaceRegistryKey ( InterfaceVersion ) , EntriesForInterface ) ;
AllInterfaceEntries . Append ( MoveTemp ( EntriesForInterface ) ) ;
}
2021-06-23 20:08:21 -04:00
2020-12-14 15:48:27 -04:00
auto IsChildClassOfRegisteredClass = [ & ] ( const IMetasoundUObjectRegistryEntry * Entry )
{
return Entry - > IsChildClass ( InClass ) ;
} ;
2021-11-22 15:55:50 -05:00
if ( const IMetasoundUObjectRegistryEntry * const * EntryForClass = AllInterfaceEntries . FindByPredicate ( IsChildClassOfRegisteredClass ) )
2020-12-14 15:48:27 -04:00
{
2021-06-23 20:08:21 -04:00
return NewObject ( * * EntryForClass , InDocument , InPath ) ;
2020-12-14 15:48:27 -04:00
}
return nullptr ;
}
bool IsRegisteredClass ( UObject * InObject ) const override
{
return ( nullptr ! = GetEntryByUObject ( InObject ) ) ;
}
FMetasoundAssetBase * GetObjectAsAssetBase ( UObject * InObject ) const override
{
if ( const IMetasoundUObjectRegistryEntry * Entry = GetEntryByUObject ( InObject ) )
{
return Entry - > Cast ( InObject ) ;
}
return nullptr ;
}
const FMetasoundAssetBase * GetObjectAsAssetBase ( const UObject * InObject ) const override
{
if ( const IMetasoundUObjectRegistryEntry * Entry = GetEntryByUObject ( InObject ) )
{
return Entry - > Cast ( InObject ) ;
}
return nullptr ;
}
private :
2021-01-13 10:48:59 -04:00
UObject * NewObject ( const IMetasoundUObjectRegistryEntry & InEntry , const FMetasoundFrontendDocument & InDocument , const FString & InPath ) const
2020-12-14 15:48:27 -04:00
{
UPackage * PackageToSaveTo = nullptr ;
if ( GIsEditor )
{
FText InvalidPathReason ;
bool const bValidPackageName = FPackageName : : IsValidLongPackageName ( InPath , false , & InvalidPathReason ) ;
if ( ! ensureAlwaysMsgf ( bValidPackageName , TEXT ( " Tried to generate a Metasound UObject with an invalid package path/name Falling back to transient package, which means we won't be able to save this asset. " ) ) )
{
PackageToSaveTo = GetTransientPackage ( ) ;
}
else
{
PackageToSaveTo = CreatePackage ( * InPath ) ;
}
}
else
{
PackageToSaveTo = GetTransientPackage ( ) ;
}
2021-07-27 15:36:03 -04:00
UObject * NewMetasoundObject = InEntry . NewObject ( PackageToSaveTo , * InDocument . RootGraph . Metadata . GetClassName ( ) . GetFullName ( ) . ToString ( ) ) ;
2020-12-14 15:48:27 -04:00
FMetasoundAssetBase * NewAssetBase = InEntry . Cast ( NewMetasoundObject ) ;
if ( ensure ( nullptr ! = NewAssetBase ) )
{
NewAssetBase - > SetDocument ( InDocument ) ;
}
# if WITH_EDITOR
AsyncTask ( ENamedThreads : : GameThread , [ NewMetasoundObject ] ( )
{
FAssetRegistryModule : : AssetCreated ( NewMetasoundObject ) ;
NewMetasoundObject - > MarkPackageDirty ( ) ;
// todo: how do you get the package for a uobject and save it? I forget
} ) ;
# endif
return NewMetasoundObject ;
}
const IMetasoundUObjectRegistryEntry * FindEntryByPredicate ( TFunction < bool ( const IMetasoundUObjectRegistryEntry * ) > InPredicate ) const
{
const IMetasoundUObjectRegistryEntry * const * Entry = Entries . FindByPredicate ( InPredicate ) ;
if ( nullptr = = Entry )
{
return nullptr ;
}
return * Entry ;
}
TArray < const IMetasoundUObjectRegistryEntry * > FindEntriesByPredicate ( TFunction < bool ( const IMetasoundUObjectRegistryEntry * ) > InPredicate ) const
{
TArray < const IMetasoundUObjectRegistryEntry * > FoundEntries ;
Algo : : CopyIf ( Entries , FoundEntries , InPredicate ) ;
return FoundEntries ;
}
const IMetasoundUObjectRegistryEntry * GetEntryByUObject ( const UObject * InObject ) const
{
auto IsChildClassOfRegisteredClass = [ & ] ( const IMetasoundUObjectRegistryEntry * Entry )
{
if ( nullptr = = Entry )
{
return false ;
}
return Entry - > IsChildClass ( InObject ) ;
} ;
return FindEntryByPredicate ( IsChildClassOfRegisteredClass ) ;
}
TArray < TUniquePtr < IMetasoundUObjectRegistryEntry > > Storage ;
2021-11-22 15:55:50 -05:00
TMultiMap < Frontend : : FInterfaceRegistryKey , const IMetasoundUObjectRegistryEntry * > EntriesByInterface ;
TMultiMap < FName , const IMetasoundUObjectRegistryEntry * > EntriesByName ;
2020-12-14 15:48:27 -04:00
TArray < const IMetasoundUObjectRegistryEntry * > Entries ;
} ;
IMetasoundUObjectRegistry & IMetasoundUObjectRegistry : : Get ( )
{
static FMetasoundUObjectRegistry Registry ;
return Registry ;
}
}