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"
2021-08-19 09:59:27 -04:00
# include "MetasoundFrontendDataTypeRegistry.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
# ifndef WITH_METASOUND_FRONTEND
# define WITH_METASOUND_FRONTEND 0
# endif
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 " ) ) ;
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
case EMetasoundFrontendClassType : : Graph :
return GraphType ;
default :
2021-11-18 14:37:34 -05:00
static_assert ( static_cast < uint8 > ( EMetasoundFrontendClassType : : Invalid ) = = 9 , " Missing EMetasoundFrontendClassType case coverage " ) ;
2021-06-08 10:52:31 -04:00
return InvalidType ;
}
}
2021-03-30 18:22:10 -04:00
// Registry container private implementation.
class FRegistryContainerImpl : public FMetasoundFrontendRegistryContainer
2021-02-18 13:11:33 -04:00
{
2021-03-30 18:22:10 -04:00
public :
using FConverterNodeRegistryKey = : : Metasound : : Frontend : : FConverterNodeRegistryKey ;
using FConverterNodeRegistryValue = : : Metasound : : Frontend : : FConverterNodeRegistryValue ;
using FConverterNodeInfo = : : Metasound : : Frontend : : FConverterNodeInfo ;
using FNodeRegistryKey = Metasound : : Frontend : : FNodeRegistryKey ;
2021-06-14 16:46:19 -04:00
using FDataTypeRegistryInfo = Metasound : : Frontend : : FDataTypeRegistryInfo ;
2021-03-30 18:22:10 -04:00
using FNodeClassMetadata = Metasound : : FNodeClassMetadata ;
using IEnumDataTypeInterface = Metasound : : Frontend : : IEnumDataTypeInterface ;
FRegistryContainerImpl ( ) = default ;
FRegistryContainerImpl ( const FRegistryContainerImpl & ) = delete ;
FRegistryContainerImpl & operator = ( const FRegistryContainerImpl & ) = delete ;
virtual ~ FRegistryContainerImpl ( ) = default ;
// Add a function to the init command array.
bool EnqueueInitCommand ( TUniqueFunction < void ( ) > & & InFunc ) override ;
// This is called on module startup. This invokes any registration commands enqueued by our registration macros.
void RegisterPendingNodes ( ) override ;
/** Register external node with the frontend.
*
* @ param InCreateNode - Function for creating node from FNodeInitData .
* @ param InCreateDescription - Function for creating a FMetasoundFrontendClass .
*
* @ return True on success .
*/
2021-06-14 16:46:19 -04:00
virtual FNodeRegistryKey RegisterNode ( TUniquePtr < Metasound : : Frontend : : INodeRegistryEntry > & & ) override ;
virtual bool UnregisterNode ( const FNodeRegistryKey & InKey ) override ;
virtual bool IsNodeRegistered ( const FNodeRegistryKey & InKey ) const override ;
2021-07-27 15:36:03 -04:00
virtual bool IsNodeNative ( const FNodeRegistryKey & InKey ) const override ;
2021-03-30 18:22:10 -04:00
2021-06-14 16:46:19 -04:00
bool RegisterConversionNode ( const FConverterNodeRegistryKey & InNodeKey , const FConverterNodeInfo & InNodeInfo ) override ;
2021-06-09 18:20:38 -04:00
2021-06-23 20:08:21 -04:00
virtual void ForEachNodeRegistryTransactionSince ( FRegistryTransactionID InSince , FRegistryTransactionID * OutCurrentRegistryTransactionID , TFunctionRef < void ( const FNodeRegistryTransaction & ) > InFunc ) const override ;
2021-03-30 18:22:10 -04:00
2021-05-03 17:52:04 -04:00
void IterateRegistry ( Metasound : : FIterateMetasoundFrontendClassFunction InIterFunc , EMetasoundFrontendClassType InClassType = EMetasoundFrontendClassType : : Invalid ) const override ;
2021-03-30 18:22:10 -04:00
// Find Frontend Document data.
2021-06-14 16:46:19 -04:00
bool FindFrontendClassFromRegistered ( const FNodeRegistryKey & InKey , FMetasoundFrontendClass & OutClass ) override ;
virtual bool FindNodeClassInfoFromRegistered ( const Metasound : : Frontend : : FNodeRegistryKey & InKey , FNodeClassInfo & OutInfo ) override ;
bool FindInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey ) override ;
bool FindVariableNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey ) override ;
bool FindOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey ) override ;
2021-03-30 18:22:10 -04:00
// Create a new instance of a C++ implemented node from the registry.
2021-06-14 16:46:19 -04:00
virtual TUniquePtr < Metasound : : INode > CreateNode ( const FNodeRegistryKey & InKey , const Metasound : : FNodeInitData & InInitData ) const override ;
2021-09-07 17:07:54 -04:00
virtual TUniquePtr < INode > CreateNode ( const FNodeRegistryKey & InKey , FDefaultLiteralNodeConstructorParams & & ) const override ;
virtual TUniquePtr < INode > CreateNode ( const FNodeRegistryKey & InKey , FDefaultNamedVertexNodeConstructorParams & & ) const override ;
virtual TUniquePtr < INode > CreateNode ( const FNodeRegistryKey & InKey , FDefaultNamedVertexWithLiteralNodeConstructorParams & & ) const override ;
2021-03-30 18:22:10 -04:00
// Returns a list of possible nodes to use to convert from FromDataType to ToDataType.
// Returns an empty array if none are available.
TArray < FConverterNodeInfo > GetPossibleConverterNodes ( const FName & FromDataType , const FName & ToDataType ) override ;
private :
2021-06-14 16:46:19 -04:00
const INodeRegistryEntry * FindNodeEntry ( const FNodeRegistryKey & InKey ) const ;
2021-03-30 18:22:10 -04:00
// This buffer is used to enqueue nodes and datatypes to register when the module has been initialized,
// in order to avoid bad behavior with ensures, logs, etc. on static initialization.
// The bad news is that TInlineAllocator is the safest allocator to use on static init.
// The good news is that none of these lambdas typically have captures, so this should have low memory overhead.
static constexpr int32 MaxNumNodesAndDatatypesToInitialize = 8192 ;
TArray < TUniqueFunction < void ( ) > , TInlineAllocator < MaxNumNodesAndDatatypesToInitialize > > LazyInitCommands ;
FCriticalSection LazyInitCommandCritSection ;
// Registry in which we keep all information about nodes implemented in C++.
2021-06-14 16:46:19 -04:00
TMap < FNodeRegistryKey , TUniquePtr < INodeRegistryEntry > > RegisteredNodes ;
2021-03-30 18:22:10 -04:00
// Registry in which we keep lists of possible nodes to use to convert between two datatypes
TMap < FConverterNodeRegistryKey , FConverterNodeRegistryValue > ConverterNodeRegistry ;
2021-06-23 20:08:21 -04:00
TRegistryTransactionHistory < FNodeRegistryTransaction > RegistryTransactionHistory ;
2021-03-30 18:22:10 -04:00
} ;
void FRegistryContainerImpl : : RegisterPendingNodes ( )
{
2021-12-07 18:37:04 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( metasound : : FRegistryContainerImpl : : RegisterPendingNodes ) ;
2021-03-30 18:22:10 -04:00
{
2021-12-07 18:37:04 -05:00
FScopeLock ScopeLock ( & LazyInitCommandCritSection ) ;
for ( TUniqueFunction < void ( ) > & Command : LazyInitCommands )
{
Command ( ) ;
}
LazyInitCommands . Empty ( ) ;
2021-03-30 18:22:10 -04:00
}
2021-12-07 18:37:04 -05:00
// Prime search engine after bulk registration.
ISearchEngine : : Get ( ) . Prime ( ) ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
bool FRegistryContainerImpl : : EnqueueInitCommand ( TUniqueFunction < void ( ) > & & InFunc )
2021-02-18 13:11:33 -04:00
{
2021-12-07 18:37:04 -05:00
2021-03-30 18:22:10 -04:00
FScopeLock ScopeLock ( & LazyInitCommandCritSection ) ;
if ( LazyInitCommands . Num ( ) > = MaxNumNodesAndDatatypesToInitialize )
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Registering more that %d nodes and datatypes for metasounds! Consider increasing MetasoundFrontendRegistryContainer::MaxNumNodesAndDatatypesToInitialize. " ) ) ;
2021-03-30 18:22:10 -04:00
}
LazyInitCommands . Add ( MoveTemp ( InFunc ) ) ;
return true ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-23 20:08:21 -04:00
void FRegistryContainerImpl : : ForEachNodeRegistryTransactionSince ( FRegistryTransactionID InSince , FRegistryTransactionID * OutCurrentRegistryTransactionID , TFunctionRef < void ( const FNodeRegistryTransaction & ) > InFunc ) const
2021-02-18 13:11:33 -04:00
{
2021-06-23 20:08:21 -04:00
return RegistryTransactionHistory . ForEachTransactionSince ( InSince , OutCurrentRegistryTransactionID , InFunc ) ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:46:19 -04:00
2021-09-07 17:07:54 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , const Metasound : : FNodeInitData & InInitData ) const
2021-02-18 13:11:33 -04:00
{
2021-11-07 23:43:01 -05:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-03-30 18:22:10 -04:00
{
2021-09-07 17:07:54 -04:00
return Entry - > CreateNode ( InInitData ) ;
2021-03-30 18:22:10 -04:00
}
2021-11-07 23:43:01 -05:00
// 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 ) ;
2021-06-14 16:46:19 -04:00
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 ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:46:19 -04:00
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
2021-03-30 18:22:10 -04:00
}
2021-06-14 16:46:19 -04:00
return nullptr ;
}
2021-09-07 17:07:54 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , FDefaultNamedVertexNodeConstructorParams & & InParams ) const
2021-06-14 16:46:19 -04:00
{
const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) )
{
2021-09-07 17:07:54 -04:00
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 ) ) ;
2021-06-14 16:46:19 -04:00
}
return nullptr ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
TArray < : : Metasound : : Frontend : : FConverterNodeInfo > FRegistryContainerImpl : : GetPossibleConverterNodes ( const FName & FromDataType , const FName & ToDataType )
2021-02-18 13:11:33 -04:00
{
2021-03-30 18:22:10 -04:00
FConverterNodeRegistryKey InKey = { FromDataType , ToDataType } ;
if ( ! ConverterNodeRegistry . Contains ( InKey ) )
{
return TArray < FConverterNodeInfo > ( ) ;
}
else
{
return ConverterNodeRegistry [ InKey ] . PotentialConverterNodes ;
}
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:46:19 -04:00
FNodeRegistryKey FRegistryContainerImpl : : RegisterNode ( TUniquePtr < INodeRegistryEntry > & & InEntry )
{
2021-03-30 18:22:10 -04:00
FNodeRegistryKey Key ;
2021-06-14 16:46:19 -04:00
if ( InEntry . IsValid ( ) )
2021-03-30 18:22:10 -04:00
{
2021-07-12 16:13:03 -04:00
Key = NodeRegistryKey : : CreateKey ( InEntry - > GetClassInfo ( ) ) ;
2021-06-14 16:46:19 -04:00
2021-03-30 18:22:10 -04:00
// check to see if an identical node was already registered, and log
2021-07-27 20:30:14 -04:00
ensureAlwaysMsgf (
! RegisteredNodes . Contains ( Key ) ,
TEXT ( " Node with registry key '%s' already registered. "
" 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 ) ;
2021-03-30 18:22:10 -04:00
// Store update to newly registered node in history so nodes
// can be queried by transaction ID
2021-06-23 20:08:21 -04:00
RegistryTransactionHistory . Add ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeRegistration , Key , InEntry - > GetClassInfo ( ) ) ) ;
2021-03-30 18:22:10 -04:00
2021-05-03 17:52:04 -04:00
// Store registry elements in map so nodes can be queried using registry key.
2021-06-14 16:46:19 -04:00
RegisteredNodes . Add ( Key , MoveTemp ( InEntry ) ) ;
2021-06-08 10:52:31 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-08 10:52:31 -04:00
return Key ;
}
2021-06-14 16:46:19 -04:00
bool FRegistryContainerImpl : : UnregisterNode ( const FNodeRegistryKey & InKey )
2021-06-08 10:52:31 -04:00
{
if ( IsValidNodeRegistryKey ( InKey ) )
{
2021-06-14 16:46:19 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-06-08 10:52:31 -04:00
{
2021-06-23 20:08:21 -04:00
RegistryTransactionHistory . Add ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeUnregistration , InKey , Entry - > GetClassInfo ( ) ) ) ;
2021-06-08 10:52:31 -04:00
2021-06-14 16:46:19 -04:00
RegisteredNodes . Remove ( InKey ) ;
2021-06-08 10:52:31 -04:00
return true ;
}
2021-03-30 18:22:10 -04:00
}
return false ;
}
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
{
2021-06-14 16:46:19 -04:00
return RegisteredNodes . Contains ( InKey ) ;
2021-03-30 18:22:10 -04:00
}
2021-07-27 15:36:03 -04:00
bool FRegistryContainerImpl : : IsNodeNative ( const FNodeRegistryKey & InKey ) const
{
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
{
return Entry - > IsNative ( ) ;
}
return false ;
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:46:19 -04:00
bool FRegistryContainerImpl : : FindFrontendClassFromRegistered ( const FNodeRegistryKey & InKey , FMetasoundFrontendClass & OutClass )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:46:19 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:46:19 -04:00
OutClass = Entry - > GetFrontendClass ( ) ;
2021-05-28 14:09:45 -04:00
return true ;
}
return false ;
}
2021-06-14 16:46:19 -04:00
bool FRegistryContainerImpl : : FindNodeClassInfoFromRegistered ( const Metasound : : Frontend : : FNodeRegistryKey & InKey , FNodeClassInfo & OutInfo )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:46:19 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:46:19 -04:00
OutInfo = Entry - > GetClassInfo ( ) ;
return true ;
}
return false ;
}
bool FRegistryContainerImpl : : FindInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
2021-08-19 09:59:27 -04:00
FMetasoundFrontendClass Class ;
if ( IDataTypeRegistry : : Get ( ) . GetFrontendInputClass ( InDataTypeName , Class ) )
2021-06-14 16:46:19 -04:00
{
2021-08-19 09:59:27 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
2021-03-30 18:22:10 -04:00
return true ;
}
return false ;
}
2021-06-14 16:46:19 -04:00
bool FRegistryContainerImpl : : FindVariableNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2021-03-30 18:22:10 -04:00
{
2021-08-19 09:59:27 -04:00
FMetasoundFrontendClass Class ;
2021-09-07 17:07:54 -04:00
if ( IDataTypeRegistry : : Get ( ) . GetFrontendLiteralClass ( InDataTypeName , Class ) )
2021-03-30 18:22:10 -04:00
{
2021-08-19 09:59:27 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
2021-06-14 16:46:19 -04:00
return true ;
}
return false ;
}
bool FRegistryContainerImpl : : FindOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
2021-08-19 09:59:27 -04:00
FMetasoundFrontendClass Class ;
if ( IDataTypeRegistry : : Get ( ) . GetFrontendOutputClass ( InDataTypeName , Class ) )
2021-06-14 16:46:19 -04:00
{
2021-08-19 09:59:27 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Class . Metadata ) ;
2021-03-30 18:22:10 -04:00
return true ;
}
return false ;
2021-02-18 13:11:33 -04:00
}
2021-05-03 17:52:04 -04:00
void FRegistryContainerImpl : : IterateRegistry ( Metasound : : FIterateMetasoundFrontendClassFunction InIterFunc , EMetasoundFrontendClassType InClassType ) const
{
2021-06-14 16:46:19 -04:00
auto WrappedFunc = [ & ] ( const TPair < FNodeRegistryKey , TUniquePtr < INodeRegistryEntry > > & Pair )
2021-05-03 17:52:04 -04:00
{
2021-06-14 16:46:19 -04:00
InIterFunc ( Pair . Value - > GetFrontendClass ( ) ) ;
2021-05-03 17:52:04 -04:00
} ;
2021-06-14 16:46:19 -04:00
if ( EMetasoundFrontendClassType : : Invalid = = InClassType )
2021-05-03 17:52:04 -04:00
{
2021-06-14 16:46:19 -04:00
// Iterate through all classes.
Algo : : ForEach ( RegisteredNodes , WrappedFunc ) ;
2021-05-03 17:52:04 -04:00
}
2021-06-14 16:46:19 -04:00
else
{
// Only call function on classes of certain type.
auto IsMatchingClassType = [ & ] ( const TPair < FNodeRegistryKey , TUniquePtr < INodeRegistryEntry > > & Pair )
{
return Pair . Value - > GetClassInfo ( ) . Type = = InClassType ;
} ;
Algo : : ForEachIf ( RegisteredNodes , IsMatchingClassType , WrappedFunc ) ;
}
}
const INodeRegistryEntry * FRegistryContainerImpl : : FindNodeEntry ( const FNodeRegistryKey & InKey ) const
{
if ( const TUniquePtr < INodeRegistryEntry > * Entry = RegisteredNodes . Find ( InKey ) )
{
if ( Entry - > IsValid ( ) )
{
return Entry - > Get ( ) ;
}
}
return nullptr ;
2021-05-03 17:52:04 -04:00
}
2021-06-09 18:20:38 -04:00
} // namespace MetasoundFrontendRegistriesPrivate
2021-06-08 10:52:31 -04:00
2021-06-23 20:08:21 -04:00
FNodeRegistryTransaction : : FNodeRegistryTransaction ( ETransactionType InType , const FNodeRegistryKey & InKey , const FNodeClassInfo & InNodeClassInfo )
: Type ( InType )
, Key ( InKey )
, NodeClassInfo ( InNodeClassInfo )
{
}
FNodeRegistryTransaction : : ETransactionType FNodeRegistryTransaction : : GetTransactionType ( ) const
{
return Type ;
}
const FNodeClassInfo & FNodeRegistryTransaction : : GetNodeClassInfo ( ) const
{
return NodeClassInfo ;
}
const FNodeRegistryKey & FNodeRegistryTransaction : : GetNodeRegistryKey ( ) const
{
return Key ;
}
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 ;
FString RegistryKey = FString : : Format ( TEXT ( " {0}_{1}_{2}.{3} " ) , { * GetClassTypeString ( InType ) , * InFullClassName , InMajorVersion , InMinorVersion } ) ;
return RegistryKey ;
}
bool IsValid ( const FNodeRegistryKey & InKey )
{
return ! InKey . IsEmpty ( ) ;
}
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-08 10:52:31 -04:00
bool IsValidNodeRegistryKey ( const FNodeRegistryKey & InKey )
{
2021-07-12 16:13:03 -04:00
return NodeRegistryKey : : IsValid ( InKey ) ;
2021-06-08 10:52:31 -04:00
}
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
{
}
2021-06-16 11:21:13 -04:00
FNodeClassInfo : : FNodeClassInfo ( const FMetasoundFrontendGraphClass & InClass , FName 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
{
2021-06-16 11:21:13 -04:00
ensure ( ! AssetPath . IsNone ( ) ) ;
2021-06-14 16:46:19 -04:00
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 ) ;
}
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 : : LazySingleton = nullptr ;
FMetasoundFrontendRegistryContainer * FMetasoundFrontendRegistryContainer : : Get ( )
{
if ( ! LazySingleton )
{
2021-03-30 18:22:10 -04:00
LazySingleton = new Metasound : : Frontend : : MetasoundFrontendRegistryPrivate : : FRegistryContainerImpl ( ) ;
2020-07-20 00:05:22 -04:00
}
return LazySingleton ;
}
void FMetasoundFrontendRegistryContainer : : ShutdownMetasoundFrontend ( )
{
if ( LazySingleton )
{
delete LazySingleton ;
LazySingleton = nullptr ;
}
}
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 )
2021-05-28 14:09:45 -04:00
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
2021-06-14 16:46:19 -04:00
return Registry - > FindInputNodeRegistryKeyForDataType ( InDataTypeName , 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 )
{
if ( FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) )
{
return Registry - > FindOutputNodeRegistryKeyForDataType ( InDataTypeName , OutKey ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}