2020-07-20 00:05:22 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundFrontendRegistries.h"
2021-01-13 10:48:59 -04:00
2021-06-14 16:46:19 -04:00
# include "Algo/ForEach.h"
2020-07-20 00:05:22 -04:00
# include "CoreMinimal.h"
2022-01-13 10:27:49 -05:00
# include "HAL/PlatformTime.h"
2021-08-19 09:59:27 -04:00
# include "MetasoundFrontendDataTypeRegistry.h"
2022-05-09 09:50:28 -04:00
# include "MetasoundFrontendNodeRegistryPrivate.h"
2021-03-30 18:22:10 -04:00
# include "MetasoundFrontendRegistryTransaction.h"
2021-12-07 18:37:04 -05:00
# include "MetasoundFrontendSearchEngine.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundLog.h"
2021-03-05 20:06:54 -04:00
# include "MetasoundRouter.h"
2021-12-07 18:37:04 -05:00
# include "MetasoundTrace.h"
2020-07-20 13:14:38 -04:00
# include "Misc/ScopeLock.h"
2020-07-20 00:05:22 -04:00
2021-02-18 13:11:33 -04:00
namespace Metasound
2020-11-24 15:24:29 -04:00
{
2021-03-30 18:22:10 -04:00
namespace Frontend
2020-11-24 15:24:29 -04:00
{
2021-03-30 18:22:10 -04:00
namespace MetasoundFrontendRegistryPrivate
2021-02-18 13:11:33 -04:00
{
2021-06-08 10:52:31 -04:00
const FString & GetClassTypeString ( EMetasoundFrontendClassType InType )
2021-03-30 18:22:10 -04:00
{
2021-06-08 10:52:31 -04:00
static const FString InputType ( TEXT ( " Input " ) ) ;
static const FString OutputType ( TEXT ( " Output " ) ) ;
static const FString ExternalType ( TEXT ( " External " ) ) ;
2021-10-12 21:21:22 -04:00
static const FString VariableAccessorType ( TEXT ( " VariableAccessor " ) ) ;
2021-11-18 14:37:34 -05:00
static const FString VariableDeferredAccessorType ( TEXT ( " VariableDeferredAccessor " ) ) ;
2021-10-12 21:21:22 -04:00
static const FString VariableMutatorType ( TEXT ( " VariableMutator " ) ) ;
2021-06-08 10:52:31 -04:00
static const FString VariableType ( TEXT ( " Variable " ) ) ;
2021-10-12 21:21:22 -04:00
static const FString LiteralType ( TEXT ( " Literal " ) ) ;
2021-06-08 10:52:31 -04:00
static const FString GraphType ( TEXT ( " Graph " ) ) ;
2022-08-10 14:18:10 -04:00
static const FString TemplateType ( TEXT ( " Template " ) ) ;
2021-06-08 10:52:31 -04:00
static const FString InvalidType ( TEXT ( " Invalid " ) ) ;
switch ( InType )
{
case EMetasoundFrontendClassType : : Input :
return InputType ;
case EMetasoundFrontendClassType : : Output :
return OutputType ;
case EMetasoundFrontendClassType : : External :
return ExternalType ;
2021-10-12 21:21:22 -04:00
case EMetasoundFrontendClassType : : Literal :
return LiteralType ;
2021-06-08 10:52:31 -04:00
case EMetasoundFrontendClassType : : Variable :
return VariableType ;
2021-10-12 21:21:22 -04:00
2021-11-18 14:37:34 -05:00
case EMetasoundFrontendClassType : : VariableDeferredAccessor :
return VariableDeferredAccessorType ;
2021-10-12 21:21:22 -04:00
case EMetasoundFrontendClassType : : VariableAccessor :
return VariableAccessorType ;
case EMetasoundFrontendClassType : : VariableMutator :
return VariableMutatorType ;
2021-06-08 10:52:31 -04:00
2022-08-10 14:18:10 -04:00
case EMetasoundFrontendClassType : : Template :
return TemplateType ;
2021-06-08 10:52:31 -04:00
case EMetasoundFrontendClassType : : Graph :
return GraphType ;
default :
2022-08-10 14:18:10 -04:00
static_assert ( static_cast < uint8 > ( EMetasoundFrontendClassType : : Invalid ) = = 10 , " Missing EMetasoundFrontendClassType case coverage " ) ;
2021-06-08 10:52:31 -04:00
return InvalidType ;
}
}
2022-05-09 09:50:28 -04:00
}
2021-06-08 10:52:31 -04:00
2022-05-09 09:50:28 -04:00
FRegistryContainerImpl * FRegistryContainerImpl : : LazySingleton = nullptr ;
FRegistryContainerImpl & FRegistryContainerImpl : : Get ( )
{
if ( ! LazySingleton )
2021-02-18 13:11:33 -04:00
{
2022-05-09 09:50:28 -04:00
LazySingleton = new Metasound : : Frontend : : FRegistryContainerImpl ( ) ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2022-05-09 09:50:28 -04:00
return * LazySingleton ;
}
2021-12-07 18:37:04 -05:00
2022-05-09 09:50:28 -04:00
void FRegistryContainerImpl : : Shutdown ( )
{
if ( nullptr ! = LazySingleton )
{
delete LazySingleton ;
LazySingleton = nullptr ;
}
}
FRegistryContainerImpl : : FRegistryContainerImpl ( )
: TransactionBuffer ( MakeShared < FNodeRegistryTransactionBuffer > ( ) )
{
}
void FRegistryContainerImpl : : RegisterPendingNodes ( )
{
METASOUND_LLM_SCOPE ;
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( metasound : : FRegistryContainerImpl : : RegisterPendingNodes ) ;
{
2021-03-30 18:22:10 -04:00
FScopeLock ScopeLock ( & LazyInitCommandCritSection ) ;
2022-05-09 09:50:28 -04:00
for ( TUniqueFunction < void ( ) > & Command : LazyInitCommands )
2021-03-30 18:22:10 -04:00
{
2022-05-09 09:50:28 -04:00
Command ( ) ;
2021-03-30 18:22:10 -04:00
}
2022-05-09 09:50:28 -04:00
LazyInitCommands . Empty ( ) ;
}
// Prime search engine after bulk registration.
ISearchEngine : : Get ( ) . Prime ( ) ;
}
bool FRegistryContainerImpl : : EnqueueInitCommand ( TUniqueFunction < void ( ) > & & InFunc )
{
FScopeLock ScopeLock ( & LazyInitCommandCritSection ) ;
if ( LazyInitCommands . Num ( ) > = MaxNumNodesAndDatatypesToInitialize )
{
2023-05-26 15:52:39 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Registering more that %d nodes and datatypes for metasounds! Consider increasing MetasoundFrontendRegistryContainer::MaxNumNodesAndDatatypesToInitialize. " ) , MaxNumNodesAndDatatypesToInitialize ) ;
2022-05-09 09:50:28 -04:00
}
LazyInitCommands . Add ( MoveTemp ( InFunc ) ) ;
return true ;
}
void FRegistryContainerImpl : : ForEachNodeRegistryTransactionSince ( FRegistryTransactionID InSince , FRegistryTransactionID * OutCurrentRegistryTransactionID , TFunctionRef < void ( const FNodeRegistryTransaction & ) > InFunc ) const
{
UE_LOG ( LogMetaSound , Error , TEXT ( " FMetasoundFrontendRegistryContainer::ForEachNodeRegistryTransactionSince is no longer supported and will not function as expected. " ) ) ;
}
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , const Metasound : : FNodeInitData & InInitData ) const
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
return Entry - > CreateNode ( InInitData ) ;
}
// Because creation of external nodes can rely on assets being unavailable due to errors in loading order, asset(s)
// missing, etc. only log error and don't throw ensure to avoid blocking start-up if assets are missing. All other
// CreateNode calls are natively managed and thus better suited to throw ensures.
UE_LOG ( LogMetaSound , Error , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) ;
return nullptr ;
}
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , FDefaultLiteralNodeConstructorParams & & InParams ) const
{
const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) )
{
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , FDefaultNamedVertexNodeConstructorParams & & InParams ) const
{
const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) )
{
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , FDefaultNamedVertexWithLiteralNodeConstructorParams & & InParams ) const
{
const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) )
{
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
TArray < : : Metasound : : Frontend : : FConverterNodeInfo > FRegistryContainerImpl : : GetPossibleConverterNodes ( const FName & FromDataType , const FName & ToDataType )
{
FConverterNodeRegistryKey InKey = { FromDataType , ToDataType } ;
if ( ! ConverterNodeRegistry . Contains ( InKey ) )
{
return TArray < FConverterNodeInfo > ( ) ;
}
else
{
return ConverterNodeRegistry [ InKey ] . PotentialConverterNodes ;
}
}
TUniquePtr < FNodeRegistryTransactionStream > FRegistryContainerImpl : : CreateTransactionStream ( )
{
return MakeUnique < FNodeRegistryTransactionStream > ( TransactionBuffer ) ;
}
FNodeRegistryKey FRegistryContainerImpl : : RegisterNode ( TUniquePtr < INodeRegistryEntry > & & InEntry )
{
METASOUND_LLM_SCOPE ;
FNodeRegistryKey Key ;
if ( InEntry . IsValid ( ) )
{
TSharedRef < INodeRegistryEntry , ESPMode : : ThreadSafe > Entry ( InEntry . Release ( ) ) ;
FNodeRegistryTransaction : : FTimeType Timestamp = FPlatformTime : : Cycles64 ( ) ;
Key = NodeRegistryKey : : CreateKey ( Entry - > GetClassInfo ( ) ) ;
// check to see if an identical node was already registered, and log
2023-06-28 17:05:14 -04:00
if ( RegisteredNodes . Contains ( Key ) )
{
TSharedRef < INodeRegistryEntry , ESPMode : : ThreadSafe > Node = RegisteredNodes [ Key ] ;
const FNodeClassInfo & ClassInfo = Node - > GetClassInfo ( ) ;
UE_LOG ( LogMetaSound , Error , TEXT ( " Node with registry key '%s' already registered by asset '%s'. The previously registered node will be overwritten. "
" This can happen if two classes share the same name or if METASOUND_REGISTER_NODE is defined in a public header. "
) , * Key , * ClassInfo . AssetPath . ToString ( ) ) ;
}
2022-05-09 09:50:28 -04:00
// Store update to newly registered node in history so nodes
// can be queried by transaction ID
TransactionBuffer - > AddTransaction ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeRegistration , Entry - > GetClassInfo ( ) , Timestamp ) ) ;
// Store registry elements in map so nodes can be queried using registry key.
RegisteredNodes . Add ( Key , Entry ) ;
}
return Key ;
}
2022-08-12 14:22:05 -04:00
FNodeRegistryKey FRegistryContainerImpl : : RegisterNodeTemplate ( TUniquePtr < INodeRegistryTemplateEntry > & & InEntry )
2022-08-10 14:18:10 -04:00
{
METASOUND_LLM_SCOPE ;
FNodeRegistryKey Key ;
if ( InEntry . IsValid ( ) )
{
2022-08-12 14:22:05 -04:00
TSharedRef < INodeRegistryTemplateEntry , ESPMode : : ThreadSafe > Entry ( InEntry . Release ( ) ) ;
2022-08-10 14:18:10 -04:00
FNodeRegistryTransaction : : FTimeType Timestamp = FPlatformTime : : Cycles64 ( ) ;
Key = NodeRegistryKey : : CreateKey ( Entry - > GetClassInfo ( ) ) ;
// check to see if an identical node was already registered, and log
ensureAlwaysMsgf (
! RegisteredNodes . Contains ( Key ) ,
TEXT ( " Node template with registry key '%s' already registered. The previously registered node will be overwritten. " ) ,
* Key ) ;
// Store update to newly registered node in history so nodes
// can be queried by transaction ID
TransactionBuffer - > AddTransaction ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeRegistration , Entry - > GetClassInfo ( ) , Timestamp ) ) ;
// Store registry elements in map so nodes can be queried using registry key.
RegisteredNodeTemplates . Add ( Key , Entry ) ;
}
return Key ;
}
2022-05-09 09:50:28 -04:00
bool FRegistryContainerImpl : : UnregisterNode ( const FNodeRegistryKey & InKey )
{
METASOUND_LLM_SCOPE ;
if ( NodeRegistryKey : : IsValid ( InKey ) )
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
FNodeRegistryTransaction : : FTimeType Timestamp = FPlatformTime : : Cycles64 ( ) ;
TransactionBuffer - > AddTransaction ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeUnregistration , Entry - > GetClassInfo ( ) , Timestamp ) ) ;
RegisteredNodes . Remove ( InKey ) ;
return true ;
}
}
return false ;
}
2022-08-10 14:18:10 -04:00
bool FRegistryContainerImpl : : UnregisterNodeTemplate ( const FNodeRegistryKey & InKey )
{
METASOUND_LLM_SCOPE ;
if ( NodeRegistryKey : : IsValid ( InKey ) )
{
2022-08-12 14:22:05 -04:00
if ( const INodeRegistryTemplateEntry * Entry = FindNodeTemplateEntry ( InKey ) )
2022-08-10 14:18:10 -04:00
{
FNodeRegistryTransaction : : FTimeType Timestamp = FPlatformTime : : Cycles64 ( ) ;
TransactionBuffer - > AddTransaction ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeUnregistration , Entry - > GetClassInfo ( ) , Timestamp ) ) ;
RegisteredNodeTemplates . Remove ( InKey ) ;
return true ;
}
}
return false ;
}
2022-05-09 09:50:28 -04:00
bool FRegistryContainerImpl : : RegisterConversionNode ( const FConverterNodeRegistryKey & InNodeKey , const FConverterNodeInfo & InNodeInfo )
{
if ( ! ConverterNodeRegistry . Contains ( InNodeKey ) )
{
ConverterNodeRegistry . Add ( InNodeKey ) ;
}
FConverterNodeRegistryValue & ConverterNodeList = ConverterNodeRegistry [ InNodeKey ] ;
if ( ensureAlways ( ! ConverterNodeList . PotentialConverterNodes . Contains ( InNodeInfo ) ) )
{
ConverterNodeList . PotentialConverterNodes . Add ( InNodeInfo ) ;
return true ;
}
else
{
// If we hit this, someone attempted to add the same converter node to our list multiple times.
return false ;
}
}
bool FRegistryContainerImpl : : IsNodeRegistered ( const FNodeRegistryKey & InKey ) const
{
2022-08-10 14:18:10 -04:00
return RegisteredNodes . Contains ( InKey ) | | RegisteredNodeTemplates . Contains ( InKey ) ;
2022-05-09 09:50:28 -04:00
}
bool FRegistryContainerImpl : : IsNodeNative ( const FNodeRegistryKey & InKey ) const
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
return Entry - > IsNative ( ) ;
}
2022-08-12 14:22:05 -04:00
if ( const INodeRegistryTemplateEntry * TemplateEntry = FindNodeTemplateEntry ( InKey ) )
2022-08-10 14:18:10 -04:00
{
return true ;
}
2022-05-09 09:50:28 -04:00
return false ;
}
bool FRegistryContainerImpl : : FindFrontendClassFromRegistered ( const FNodeRegistryKey & InKey , FMetasoundFrontendClass & OutClass )
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
OutClass = Entry - > GetFrontendClass ( ) ;
return true ;
}
2022-08-10 14:18:10 -04:00
2022-08-12 14:22:05 -04:00
if ( const INodeRegistryTemplateEntry * Entry = FindNodeTemplateEntry ( InKey ) )
2022-08-10 14:18:10 -04:00
{
OutClass = Entry - > GetFrontendClass ( ) ;
return true ;
}
2022-05-09 09:50:28 -04:00
return false ;
}
2023-06-22 14:43:52 -04:00
const TSet < FMetasoundFrontendVersion > * FRegistryContainerImpl : : FindImplementedInterfacesFromRegistered ( const Metasound : : Frontend : : FNodeRegistryKey & InKey ) const
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
return Entry - > GetImplementedInterfaces ( ) ;
}
return nullptr ;
}
2022-05-09 09:50:28 -04:00
bool FRegistryContainerImpl : : FindNodeClassInfoFromRegistered ( const Metasound : : Frontend : : FNodeRegistryKey & InKey , FNodeClassInfo & OutInfo )
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
OutInfo = Entry - > GetClassInfo ( ) ;
2021-03-30 18:22:10 -04:00
return true ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2022-08-12 14:22:05 -04:00
if ( const INodeRegistryTemplateEntry * Entry = FindNodeTemplateEntry ( InKey ) )
2022-08-10 14:18:10 -04:00
{
OutInfo = Entry - > GetClassInfo ( ) ;
return true ;
}
2022-05-09 09:50:28 -04:00
return false ;
}
bool FRegistryContainerImpl : : FindInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2022-07-18 17:14:25 -04:00
{
UE_LOG ( LogMetaSound , Error , TEXT ( " FRegistryContainerImpl::FindInputNodeRegistryKeyForDataType with these parameters is no longer supported and should not be called. Use the one with EMetasoundFrontendVertexAccessType instead. " ) ) ;
return false ;
}
bool FRegistryContainerImpl : : FindInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , const EMetasoundFrontendVertexAccessType InAccessType , FNodeRegistryKey & OutKey )
2022-05-09 09:50:28 -04:00
{
FMetasoundFrontendClass Class ;
2022-09-13 21:51:22 -04:00
switch ( InAccessType )
2021-02-18 13:11:33 -04:00
{
2022-09-13 21:51:22 -04:00
case EMetasoundFrontendVertexAccessType : : Reference :
2022-07-18 17:14:25 -04:00
{
2022-09-13 21:51:22 -04:00
if ( IDataTypeRegistry : : Get ( ) . GetFrontendInputClass ( InDataTypeName , Class ) )
{
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
return true ;
}
2022-07-18 17:14:25 -04:00
}
2022-09-13 21:51:22 -04:00
break ;
case EMetasoundFrontendVertexAccessType : : Value :
2022-07-18 17:14:25 -04:00
{
2022-09-13 21:51:22 -04:00
if ( IDataTypeRegistry : : Get ( ) . GetFrontendConstructorInputClass ( InDataTypeName , Class ) )
{
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
return true ;
}
2022-07-18 17:14:25 -04:00
}
2022-09-13 21:51:22 -04:00
break ;
default :
case EMetasoundFrontendVertexAccessType : : Unset :
{
return false ;
}
break ;
2021-02-18 13:11:33 -04:00
}
2022-09-13 21:51:22 -04:00
2022-05-09 09:50:28 -04:00
return false ;
}
2021-03-30 18:22:10 -04:00
2022-05-09 09:50:28 -04:00
bool FRegistryContainerImpl : : FindVariableNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
FMetasoundFrontendClass Class ;
if ( IDataTypeRegistry : : Get ( ) . GetFrontendLiteralClass ( InDataTypeName , Class ) )
2021-02-18 13:11:33 -04:00
{
2022-05-09 09:50:28 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
return true ;
2021-06-14 16:46:19 -04:00
}
2022-05-09 09:50:28 -04:00
return false ;
}
2021-06-14 16:46:19 -04:00
2022-05-09 09:50:28 -04:00
bool FRegistryContainerImpl : : FindOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2022-07-18 17:14:25 -04:00
{
2022-08-10 14:52:01 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " FRegistryContainerImpl::FindOutputNodeRegistryKeyForDataType with these parameters is no longer supported and should not be called. Use the one with EMetasoundFrontendVertexAccessType instead. " ) ) ;
2022-07-18 17:14:25 -04:00
return false ;
}
bool FRegistryContainerImpl : : FindOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , const EMetasoundFrontendVertexAccessType InAccessType , FNodeRegistryKey & OutKey )
2022-05-09 09:50:28 -04:00
{
FMetasoundFrontendClass Class ;
2022-09-13 21:51:22 -04:00
switch ( InAccessType )
2021-06-14 16:46:19 -04:00
{
2022-09-13 21:51:22 -04:00
case EMetasoundFrontendVertexAccessType : : Reference :
2022-07-18 17:14:25 -04:00
{
2022-09-13 21:51:22 -04:00
if ( IDataTypeRegistry : : Get ( ) . GetFrontendOutputClass ( InDataTypeName , Class ) )
{
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
return true ;
}
2022-07-18 17:14:25 -04:00
}
2022-09-13 21:51:22 -04:00
break ;
case EMetasoundFrontendVertexAccessType : : Value :
2022-07-18 17:14:25 -04:00
{
2022-09-13 21:51:22 -04:00
if ( IDataTypeRegistry : : Get ( ) . GetFrontendConstructorOutputClass ( InDataTypeName , Class ) )
{
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
return true ;
}
2022-07-18 17:14:25 -04:00
}
2022-09-13 21:51:22 -04:00
break ;
2022-07-18 17:14:25 -04:00
}
2022-05-09 09:50:28 -04:00
return false ;
}
2021-06-14 16:46:19 -04:00
2022-05-09 09:50:28 -04:00
void FRegistryContainerImpl : : IterateRegistry ( Metasound : : FIterateMetasoundFrontendClassFunction InIterFunc , EMetasoundFrontendClassType InClassType ) const
{
auto WrappedFunc = [ & ] ( const TPair < FNodeRegistryKey , TSharedPtr < INodeRegistryEntry , ESPMode : : ThreadSafe > > & Pair )
2021-06-14 16:46:19 -04:00
{
2022-05-09 09:50:28 -04:00
InIterFunc ( Pair . Value - > GetFrontendClass ( ) ) ;
} ;
2021-06-14 16:46:19 -04:00
2022-05-09 09:50:28 -04:00
if ( EMetasoundFrontendClassType : : Invalid = = InClassType )
{
// Iterate through all classes.
Algo : : ForEach ( RegisteredNodes , WrappedFunc ) ;
2021-09-07 17:07:54 -04:00
}
2022-05-09 09:50:28 -04:00
else
2021-09-07 17:07:54 -04:00
{
2022-05-09 09:50:28 -04:00
// Only call function on classes of certain type.
auto IsMatchingClassType = [ & ] ( const TPair < FNodeRegistryKey , TSharedPtr < INodeRegistryEntry , ESPMode : : ThreadSafe > > & Pair )
2021-09-07 17:07:54 -04:00
{
2022-05-09 09:50:28 -04:00
return Pair . Value - > GetClassInfo ( ) . Type = = InClassType ;
2021-05-03 17:52:04 -04:00
} ;
2022-05-09 09:50:28 -04:00
Algo : : ForEachIf ( RegisteredNodes , IsMatchingClassType , WrappedFunc ) ;
2021-06-14 16:46:19 -04:00
}
2022-05-09 09:50:28 -04:00
}
2021-06-14 16:46:19 -04:00
2022-05-09 09:50:28 -04:00
const INodeRegistryEntry * FRegistryContainerImpl : : FindNodeEntry ( const FNodeRegistryKey & InKey ) const
{
if ( const TSharedRef < INodeRegistryEntry , ESPMode : : ThreadSafe > * Entry = RegisteredNodes . Find ( InKey ) )
2021-06-14 16:46:19 -04:00
{
2022-05-09 09:50:28 -04:00
return & Entry - > Get ( ) ;
2021-05-03 17:52:04 -04:00
}
2022-05-09 09:50:28 -04:00
return nullptr ;
}
2021-06-08 10:52:31 -04:00
2022-08-12 14:22:05 -04:00
const INodeRegistryTemplateEntry * FRegistryContainerImpl : : FindNodeTemplateEntry ( const FNodeRegistryKey & InKey ) const
2022-08-10 14:18:10 -04:00
{
2022-08-12 14:22:05 -04:00
if ( const TSharedRef < INodeRegistryTemplateEntry , ESPMode : : ThreadSafe > * Entry = RegisteredNodeTemplates . Find ( InKey ) )
2022-08-10 14:18:10 -04:00
{
return & Entry - > Get ( ) ;
}
return nullptr ;
}
2022-05-02 12:35:54 -04:00
FNodeRegistryTransaction : : FNodeRegistryTransaction ( ETransactionType InType , const FNodeClassInfo & InNodeClassInfo , FNodeRegistryTransaction : : FTimeType InTimestamp )
2021-06-23 20:08:21 -04:00
: Type ( InType )
, NodeClassInfo ( InNodeClassInfo )
2022-01-13 10:27:49 -05:00
, Timestamp ( InTimestamp )
2021-06-23 20:08:21 -04:00
{
}
2022-05-02 12:35:54 -04:00
FNodeRegistryTransaction : : FNodeRegistryTransaction ( ETransactionType InType , const FNodeRegistryKey & InKey , const FNodeClassInfo & InNodeClassInfo , FNodeRegistryTransaction : : FTimeType InTimestamp )
: FNodeRegistryTransaction ( InType , InNodeClassInfo , InTimestamp )
{
}
2021-06-23 20:08:21 -04:00
FNodeRegistryTransaction : : ETransactionType FNodeRegistryTransaction : : GetTransactionType ( ) const
{
return Type ;
}
const FNodeClassInfo & FNodeRegistryTransaction : : GetNodeClassInfo ( ) const
{
return NodeClassInfo ;
}
2022-05-02 12:35:54 -04:00
FNodeRegistryKey FNodeRegistryTransaction : : GetNodeRegistryKey ( ) const
2021-06-23 20:08:21 -04:00
{
2022-05-02 12:35:54 -04:00
return NodeRegistryKey : : CreateKey ( NodeClassInfo ) ;
2021-06-23 20:08:21 -04:00
}
2022-01-13 10:27:49 -05:00
FNodeRegistryTransaction : : FTimeType FNodeRegistryTransaction : : GetTimestamp ( ) const
{
return Timestamp ;
}
2021-07-12 16:13:03 -04:00
namespace NodeRegistryKey
{
// All registry keys should be created through this function to ensure consistency.
FNodeRegistryKey CreateKey ( EMetasoundFrontendClassType InType , const FString & InFullClassName , int32 InMajorVersion , int32 InMinorVersion )
{
using namespace MetasoundFrontendRegistryPrivate ;
2022-03-10 21:19:13 -05:00
const FString RegistryKey = FString : : Format ( TEXT ( " {0}_{1}_{2}.{3} " ) , { * GetClassTypeString ( InType ) , * InFullClassName , InMajorVersion , InMinorVersion } ) ;
2021-07-12 16:13:03 -04:00
return RegistryKey ;
}
2022-03-10 21:19:13 -05:00
const FNodeRegistryKey & GetInvalid ( )
{
static const FNodeRegistryKey InvalidKey ;
return InvalidKey ;
}
2021-07-12 16:13:03 -04:00
bool IsValid ( const FNodeRegistryKey & InKey )
{
2022-03-10 21:19:13 -05:00
return InKey ! = GetInvalid ( ) ;
2021-07-12 16:13:03 -04:00
}
bool IsEqual ( const FNodeRegistryKey & InLHS , const FNodeRegistryKey & InRHS )
{
return InLHS = = InRHS ;
}
bool IsEqual ( const FMetasoundFrontendClassMetadata & InLHS , const FMetasoundFrontendClassMetadata & InRHS )
{
2021-07-27 15:36:03 -04:00
if ( InLHS . GetClassName ( ) = = InRHS . GetClassName ( ) )
2021-07-12 16:13:03 -04:00
{
2021-07-27 15:36:03 -04:00
if ( InLHS . GetType ( ) = = InRHS . GetType ( ) )
2021-07-12 16:13:03 -04:00
{
2021-07-27 15:36:03 -04:00
if ( InLHS . GetVersion ( ) = = InRHS . GetVersion ( ) )
2021-07-12 16:13:03 -04:00
{
return true ;
}
}
}
return false ;
}
bool IsEqual ( const FNodeClassInfo & InLHS , const FMetasoundFrontendClassMetadata & InRHS )
{
2021-07-27 15:36:03 -04:00
if ( InLHS . ClassName = = InRHS . GetClassName ( ) )
2021-07-12 16:13:03 -04:00
{
2021-07-27 15:36:03 -04:00
if ( InLHS . Type = = InRHS . GetType ( ) )
2021-07-12 16:13:03 -04:00
{
2021-07-27 15:36:03 -04:00
if ( InLHS . Version = = InRHS . GetVersion ( ) )
2021-07-12 16:13:03 -04:00
{
return true ;
}
}
}
return false ;
}
FNodeRegistryKey CreateKey ( const FNodeClassMetadata & InNodeMetadata )
{
return CreateKey ( EMetasoundFrontendClassType : : External , InNodeMetadata . ClassName . GetFullName ( ) . ToString ( ) , InNodeMetadata . MajorVersion , InNodeMetadata . MinorVersion ) ;
}
FNodeRegistryKey CreateKey ( const FMetasoundFrontendClassMetadata & InNodeMetadata )
{
2021-07-27 15:36:03 -04:00
return CreateKey ( InNodeMetadata . GetType ( ) , InNodeMetadata . GetClassName ( ) . GetFullName ( ) . ToString ( ) , InNodeMetadata . GetVersion ( ) . Major , InNodeMetadata . GetVersion ( ) . Minor ) ;
2021-07-12 16:13:03 -04:00
}
FNodeRegistryKey CreateKey ( const FNodeClassInfo & InClassInfo )
{
return CreateKey ( InClassInfo . Type , InClassInfo . ClassName . GetFullName ( ) . ToString ( ) , InClassInfo . Version . Major , InClassInfo . Version . Minor ) ;
}
}
2021-06-14 16:46:19 -04:00
FNodeClassInfo : : FNodeClassInfo ( const FMetasoundFrontendClassMetadata & InMetadata )
2021-07-27 15:36:03 -04:00
: ClassName ( InMetadata . GetClassName ( ) )
, Type ( InMetadata . GetType ( ) )
, Version ( InMetadata . GetVersion ( ) )
2021-06-14 16:46:19 -04:00
{
}
2022-09-12 19:52:49 -04:00
FNodeClassInfo : : FNodeClassInfo ( const FMetasoundFrontendGraphClass & InClass , const FSoftObjectPath & InAssetPath )
2021-07-27 15:36:03 -04:00
: ClassName ( InClass . Metadata . GetClassName ( ) )
2021-06-16 11:21:13 -04:00
, Type ( EMetasoundFrontendClassType : : External ) // Overridden as it is considered the same as an external class in the registry
, AssetClassID ( FGuid ( ClassName . Name . ToString ( ) ) )
, AssetPath ( InAssetPath )
2021-07-27 15:36:03 -04:00
, Version ( InClass . Metadata . GetVersion ( ) )
2021-06-14 16:46:19 -04:00
{
2022-09-12 19:52:49 -04:00
ensure ( ! AssetPath . IsNull ( ) ) ;
2022-05-02 12:35:54 -04:00
# if WITH_EDITORONLY_DATA
2021-06-16 11:21:13 -04:00
for ( const FMetasoundFrontendClassInput & Input : InClass . Interface . Inputs )
{
InputTypes . Add ( Input . TypeName ) ;
}
for ( const FMetasoundFrontendClassOutput & Output : InClass . Interface . Outputs )
{
OutputTypes . Add ( Output . TypeName ) ;
}
2022-10-26 15:28:04 -04:00
bIsPreset = InClass . PresetOptions . bIsPreset ;
2022-05-02 12:35:54 -04:00
# endif // WITH_EDITORONLY_DATA
2021-06-14 16:46:19 -04:00
}
2021-06-09 18:20:38 -04:00
} // namespace Frontend
} // namespace Metasound
2020-11-24 15:24:29 -04:00
2020-07-20 00:05:22 -04:00
FMetasoundFrontendRegistryContainer * FMetasoundFrontendRegistryContainer : : Get ( )
{
2022-05-09 09:50:28 -04:00
return & Metasound : : Frontend : : FRegistryContainerImpl : : Get ( ) ;
2020-07-20 00:05:22 -04:00
}
void FMetasoundFrontendRegistryContainer : : ShutdownMetasoundFrontend ( )
{
2022-05-09 09:50:28 -04:00
Metasound : : Frontend : : FRegistryContainerImpl : : Shutdown ( ) ;
2020-07-20 00:05:22 -04:00
}
2021-01-28 19:02:51 -04:00
Metasound : : Frontend : : FNodeRegistryKey FMetasoundFrontendRegistryContainer : : GetRegistryKey ( const FNodeClassMetadata & InNodeMetadata )
2020-11-24 15:24:29 -04:00
{
2021-07-12 16:13:03 -04:00
return Metasound : : Frontend : : NodeRegistryKey : : CreateKey ( InNodeMetadata ) ;
2020-07-20 00:05:22 -04:00
}
2021-01-13 10:48:59 -04:00
Metasound : : Frontend : : FNodeRegistryKey FMetasoundFrontendRegistryContainer : : GetRegistryKey ( const FMetasoundFrontendClassMetadata & InNodeMetadata )
{
2021-07-12 16:13:03 -04:00
return Metasound : : Frontend : : NodeRegistryKey : : CreateKey ( InNodeMetadata ) ;
2021-01-13 10:48:59 -04:00
}
2021-06-14 16:46:19 -04:00
Metasound : : Frontend : : FNodeRegistryKey FMetasoundFrontendRegistryContainer : : GetRegistryKey ( const FNodeClassInfo & InClassInfo )
{
2021-07-12 16:13:03 -04:00
return Metasound : : Frontend : : NodeRegistryKey : : CreateKey ( InClassInfo ) ;
2021-06-14 16:46:19 -04:00
}
bool FMetasoundFrontendRegistryContainer : : GetFrontendClassFromRegistered ( const FNodeRegistryKey & InKey , FMetasoundFrontendClass & OutClass )
2021-01-13 10:48:59 -04:00
{
FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) ;
if ( ensure ( nullptr ! = Registry ) )
{
2021-06-14 16:46:19 -04:00
return Registry - > FindFrontendClassFromRegistered ( InKey , OutClass ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-06-14 16:46:19 -04:00
bool FMetasoundFrontendRegistryContainer : : GetNodeClassInfoFromRegistered ( const FNodeRegistryKey & InKey , FNodeClassInfo & OutInfo )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
2021-06-14 16:46:19 -04:00
return Registry - > FindNodeClassInfoFromRegistered ( InKey , OutInfo ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-06-14 16:46:19 -04:00
bool FMetasoundFrontendRegistryContainer : : GetInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2022-07-18 17:14:25 -04:00
{
UE_LOG ( LogMetaSound , Error , TEXT ( " FMetasoundFrontendRegistryContainer::GetInputNodeRegistryKeyForDataType with these parameters is no longer supported and should not be called. Use the one with EMetasoundFrontendVertexAccessType instead. " ) ) ;
return false ;
}
bool FMetasoundFrontendRegistryContainer : : GetInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , const EMetasoundFrontendVertexAccessType InAccessType , FNodeRegistryKey & OutKey )
2021-05-28 14:09:45 -04:00
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
2022-07-18 17:14:25 -04:00
return Registry - > FindInputNodeRegistryKeyForDataType ( InDataTypeName , InAccessType , OutKey ) ;
2021-05-28 14:09:45 -04:00
}
return false ;
}
2021-06-14 16:46:19 -04:00
bool FMetasoundFrontendRegistryContainer : : GetVariableNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
2021-06-14 16:46:19 -04:00
return Registry - > FindVariableNodeRegistryKeyForDataType ( InDataTypeName , OutKey ) ;
}
return false ;
}
bool FMetasoundFrontendRegistryContainer : : GetOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
2022-07-18 17:14:25 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " FMetasoundFrontendRegistryContainer::GetOutputNodeRegistryKeyForDataType with these parameters is no longer supported and should not be called. Use the one with EMetasoundFrontendVertexAccessType instead. " ) ) ;
2021-01-13 10:48:59 -04:00
return false ;
}
2022-07-18 17:14:25 -04:00
bool FMetasoundFrontendRegistryContainer : : GetOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , const EMetasoundFrontendVertexAccessType InVertexAccessType , FNodeRegistryKey & OutKey )
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
return Registry - > FindOutputNodeRegistryKeyForDataType ( InDataTypeName , InVertexAccessType , OutKey ) ;
}
return false ;
}