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:45:51 -04:00
# include "Algo/ForEach.h"
2020-07-20 00:05:22 -04:00
# include "CoreMinimal.h"
2021-03-30 18:22:10 -04:00
# include "MetasoundFrontendRegistryTransaction.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundLog.h"
2021-03-05 20:06:54 -04:00
# include "MetasoundRouter.h"
2020-07-20 13:14:38 -04:00
# include "Misc/ScopeLock.h"
# include "HAL/PlatformTime.h"
2020-07-20 00:05:22 -04:00
# ifndef WITH_METASOUND_FRONTEND
# define WITH_METASOUND_FRONTEND 0
# endif
2021-03-30 18:22:10 -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 " ) ) ;
static const FString VariableType ( TEXT ( " Variable " ) ) ;
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 ;
case EMetasoundFrontendClassType : : Variable :
return VariableType ;
case EMetasoundFrontendClassType : : Graph :
return GraphType ;
default :
static_assert ( static_cast < uint8 > ( EMetasoundFrontendClassType : : Invalid ) = = 5 , " Missing EMetasoundFrontendClassType case coverage " ) ;
return InvalidType ;
}
}
2021-02-18 13:11:33 -04:00
2021-03-30 18:22:10 -04:00
// Return the compatible literal with the most descriptive type.
// TODO: Currently TIsParsable<> allows for implicit conversion of
// constructor arguments of integral types which can cause some confusion
// here when trying to match a literal type to a constructor. For example:
//
// struct FBoolConstructibleType
// {
// FBoolConstructibleType(bool InValue);
// };
//
// static_assert(TIsParsable<FBoolConstructible, double>::Value);
//
// Implicit conversions are currently allowed in TIsParsable because this
// is perfectly legal syntax.
//
// double Value = 10.0;
// FBoolConstructibleType BoolConstructible = Value;
//
// There are some tricks to possibly disable implicit conversions when
// checking for specific constructors, but they are yet to be implemented
// and are untested. Here's the basic idea.
//
// template<DataType, DesiredIntegralArgType>
// struct TOnlyConvertIfIsSame
// {
// // Implicit conversion only defined if types match.
// template<typename SuppliedIntegralArgType, std::enable_if<std::is_same<std::decay<SuppliedIntegralArgType>::type, DesiredIntegralArgType>::value, int> = 0>
// operator DesiredIntegralArgType()
// {
// return DesiredIntegralArgType{};
// }
// };
//
// static_assert(false == std::is_constructible<FBoolConstructibleType, TOnlyConvertIfSame<double>>::value);
// static_assert(true == std::is_constructible<FBoolConstructibleType, TOnlyConvertIfSame<bool>>::value);
ELiteralType GetMostDescriptiveLiteralForDataType ( const FDataTypeRegistryInfo & InDataTypeInfo )
2021-02-18 13:11:33 -04:00
{
2021-03-30 18:22:10 -04:00
if ( InDataTypeInfo . bIsProxyArrayParsable )
{
return ELiteralType : : UObjectProxyArray ;
}
else if ( InDataTypeInfo . bIsProxyParsable )
{
return ELiteralType : : UObjectProxy ;
}
else if ( InDataTypeInfo . bIsEnum & & InDataTypeInfo . bIsIntParsable )
{
return ELiteralType : : Integer ;
}
else if ( InDataTypeInfo . bIsStringArrayParsable )
{
return ELiteralType : : StringArray ;
}
else if ( InDataTypeInfo . bIsFloatArrayParsable )
{
return ELiteralType : : FloatArray ;
}
else if ( InDataTypeInfo . bIsIntArrayParsable )
{
return ELiteralType : : IntegerArray ;
}
else if ( InDataTypeInfo . bIsBoolArrayParsable )
{
return ELiteralType : : BooleanArray ;
}
else if ( InDataTypeInfo . bIsStringParsable )
{
return ELiteralType : : String ;
}
else if ( InDataTypeInfo . bIsFloatParsable )
{
return ELiteralType : : Float ;
}
else if ( InDataTypeInfo . bIsIntParsable )
{
return ELiteralType : : Integer ;
}
else if ( InDataTypeInfo . bIsBoolParsable )
{
return ELiteralType : : Boolean ;
}
else if ( InDataTypeInfo . bIsDefaultArrayParsable )
{
return ELiteralType : : NoneArray ;
}
else if ( InDataTypeInfo . bIsDefaultParsable )
{
return ELiteralType : : None ;
}
else
{
// if we ever hit this, something has gone wrong with the REGISTER_METASOUND_DATATYPE macro.
// we should have failed to compile if any of these are false.
checkNoEntry ( ) ;
return ELiteralType : : Invalid ;
}
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
// Node registry entry for input nodes created from a data type registry entry.
class FInputNodeRegistryEntry : public INodeRegistryEntry
{
public :
FInputNodeRegistryEntry ( ) = delete ;
FInputNodeRegistryEntry ( TUniquePtr < IDataTypeRegistryEntry > & & InDataTypeEntry )
: DataTypeEntry ( MoveTemp ( InDataTypeEntry ) )
{
if ( DataTypeEntry . IsValid ( ) )
{
FrontendClass = DataTypeEntry - > GetFrontendInputClass ( ) ;
2021-06-16 11:20:44 -04:00
ClassInfo = FNodeClassInfo ( FrontendClass . Metadata ) ;
2021-06-14 16:45:51 -04:00
}
}
virtual ~ FInputNodeRegistryEntry ( ) = default ;
virtual const FNodeClassInfo & GetClassInfo ( ) const override
{
return ClassInfo ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultNodeConstructorParams & & ) const override
{
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultLiteralNodeConstructorParams & & InParams ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return DataTypeEntry - > CreateInputNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( const FNodeInitData & ) const override
{
return nullptr ;
}
virtual const FMetasoundFrontendClass & GetFrontendClass ( ) const override
{
return FrontendClass ;
}
virtual TUniquePtr < INodeRegistryEntry > Clone ( ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return MakeUnique < FInputNodeRegistryEntry > ( DataTypeEntry - > Clone ( ) ) ;
}
return MakeUnique < FInputNodeRegistryEntry > ( TUniquePtr < IDataTypeRegistryEntry > ( ) ) ;
}
private :
TUniquePtr < IDataTypeRegistryEntry > DataTypeEntry ;
FNodeClassInfo ClassInfo ;
FMetasoundFrontendClass FrontendClass ;
} ;
// Node registry entry for output nodes created from a data type registry entry.
class FOutputNodeRegistryEntry : public INodeRegistryEntry
{
public :
FOutputNodeRegistryEntry ( ) = delete ;
FOutputNodeRegistryEntry ( TUniquePtr < IDataTypeRegistryEntry > & & InDataTypeEntry )
: DataTypeEntry ( MoveTemp ( InDataTypeEntry ) )
{
if ( DataTypeEntry . IsValid ( ) )
{
FrontendClass = DataTypeEntry - > GetFrontendOutputClass ( ) ;
2021-06-16 11:20:44 -04:00
ClassInfo = FNodeClassInfo ( FrontendClass . Metadata ) ;
2021-06-14 16:45:51 -04:00
}
}
virtual ~ FOutputNodeRegistryEntry ( ) = default ;
virtual const FNodeClassInfo & GetClassInfo ( ) const override
{
return ClassInfo ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultNodeConstructorParams & & InParams ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return DataTypeEntry - > CreateOutputNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultLiteralNodeConstructorParams & & InParams ) const override
{
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( const FNodeInitData & ) const override
{
return nullptr ;
}
virtual const FMetasoundFrontendClass & GetFrontendClass ( ) const override
{
return FrontendClass ;
}
virtual TUniquePtr < INodeRegistryEntry > Clone ( ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return MakeUnique < FOutputNodeRegistryEntry > ( DataTypeEntry - > Clone ( ) ) ;
}
return MakeUnique < FOutputNodeRegistryEntry > ( TUniquePtr < IDataTypeRegistryEntry > ( ) ) ;
}
private :
TUniquePtr < IDataTypeRegistryEntry > DataTypeEntry ;
FNodeClassInfo ClassInfo ;
FMetasoundFrontendClass FrontendClass ;
} ;
// Node registry entry for variable nodes created from a data type registry entry.
class FVariableNodeRegistryEntry : public INodeRegistryEntry
{
public :
FVariableNodeRegistryEntry ( ) = delete ;
FVariableNodeRegistryEntry ( TUniquePtr < IDataTypeRegistryEntry > & & InDataTypeEntry )
: DataTypeEntry ( MoveTemp ( InDataTypeEntry ) )
{
if ( DataTypeEntry . IsValid ( ) )
{
FrontendClass = DataTypeEntry - > GetFrontendVariableClass ( ) ;
2021-06-16 11:20:44 -04:00
ClassInfo = FNodeClassInfo ( FrontendClass . Metadata ) ;
2021-06-14 16:45:51 -04:00
}
}
virtual ~ FVariableNodeRegistryEntry ( ) = default ;
virtual const FNodeClassInfo & GetClassInfo ( ) const override
{
return ClassInfo ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultNodeConstructorParams & & InParams ) const override
{
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( FDefaultLiteralNodeConstructorParams & & InParams ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return DataTypeEntry - > CreateVariableNode ( MoveTemp ( InParams ) ) ;
}
return nullptr ;
}
virtual TUniquePtr < INode > CreateNode ( const FNodeInitData & ) const override
{
return nullptr ;
}
virtual const FMetasoundFrontendClass & GetFrontendClass ( ) const override
{
return FrontendClass ;
}
virtual TUniquePtr < INodeRegistryEntry > Clone ( ) const override
{
if ( DataTypeEntry . IsValid ( ) )
{
return MakeUnique < FVariableNodeRegistryEntry > ( DataTypeEntry - > Clone ( ) ) ;
}
return MakeUnique < FVariableNodeRegistryEntry > ( TUniquePtr < IDataTypeRegistryEntry > ( ) ) ;
}
private :
TUniquePtr < IDataTypeRegistryEntry > DataTypeEntry ;
FNodeClassInfo ClassInfo ;
FMetasoundFrontendClass FrontendClass ;
} ;
2021-06-23 20:07:53 -04:00
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:45:51 -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:45:51 -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-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
bool RegisterConversionNode ( const FConverterNodeRegistryKey & InNodeKey , const FConverterNodeInfo & InNodeInfo ) override ;
2021-06-09 18:17:31 -04:00
2021-06-23 20:07:53 -04:00
virtual void ForEachNodeRegistryTransactionSince ( FRegistryTransactionID InSince , FRegistryTransactionID * OutCurrentRegistryTransactionID , TFunctionRef < void ( const FNodeRegistryTransaction & ) > InFunc ) const override ;
2021-03-30 18:22:10 -04:00
// Return any data types that can be used as a metasound input type or output type.
TArray < FName > GetAllValidDataTypes ( ) override ;
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:45:51 -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:45:51 -04:00
TUniquePtr < Metasound : : INode > CreateInputNode ( const FName & InInputType , Metasound : : FInputNodeConstructorParams & & InParams ) override ;
TUniquePtr < Metasound : : INode > CreateVariableNode ( const FName & InVariableType , FVariableNodeConstructorParams & & InParams ) override ;
TUniquePtr < Metasound : : INode > CreateOutputNode ( const FName & InOutputType , Metasound : : FOutputNodeConstructorParams & & InParams ) override ;
virtual TUniquePtr < INode > CreateNode ( const FNodeRegistryKey & InKey , FDefaultNodeConstructorParams & & ) const override ;
virtual TUniquePtr < INode > CreateNode ( const FNodeRegistryKey & InKey , FDefaultLiteralNodeConstructorParams & & ) const override ;
virtual TUniquePtr < Metasound : : INode > CreateNode ( const FNodeRegistryKey & InKey , const Metasound : : FNodeInitData & InInitData ) 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 ;
2021-06-14 16:45:51 -04:00
virtual bool RegisterDataType ( const FName & InName , TUniquePtr < Metasound : : Frontend : : IDataTypeRegistryEntry > & & ) override ;
2021-03-30 18:22:10 -04:00
// Get the desired kind of literal for a given data type. Returns EConstructorArgType::Invalid if the data type couldn't be found.
Metasound : : ELiteralType GetDesiredLiteralTypeForDataType ( FName InDataType ) const override ;
// Get whether we can build a literal of this specific type for InDataType.
bool DoesDataTypeSupportLiteralType ( FName InDataType , Metasound : : ELiteralType InLiteralType ) const override ;
// Handle uobjects and literals
UClass * GetLiteralUClassForDataType ( FName InDataType ) const override ;
2021-06-14 16:45:51 -04:00
Metasound : : FLiteral CreateLiteralFromUObject ( const FName & InDataType , UObject * InObject ) override ;
Metasound : : FLiteral CreateLiteralFromUObjectArray ( const FName & InDataType , TArray < UObject * > InObjectArray ) override ;
2021-03-30 18:22:10 -04:00
// Get info about a specific data type (what kind of literals we can use, etc.)
// @returns false if InDataType wasn't found in the registry.
bool GetInfoForDataType ( FName InDataType , FDataTypeRegistryInfo & OutInfo ) override ;
TSharedPtr < const Metasound : : Frontend : : IEnumDataTypeInterface > GetEnumInterfaceForDataType ( FName InDataType ) const override ;
TSharedPtr < Metasound : : IDataChannel , ESPMode : : ThreadSafe > CreateDataChannelForDataType ( const FName & InDataType , const Metasound : : FOperatorSettings & InOperatorSettings ) const override ;
private :
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * FindDataTypeEntry ( const FName & InDataTypeName ) const ;
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:45:51 -04:00
TMap < FNodeRegistryKey , TUniquePtr < INodeRegistryEntry > > RegisteredNodes ;
TMap < FName , TUniquePtr < IDataTypeRegistryEntry > > RegisteredDataTypes ;
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:07:53 -04:00
TRegistryTransactionHistory < FNodeRegistryTransaction > RegistryTransactionHistory ;
2021-03-30 18:22:10 -04:00
} ;
void FRegistryContainerImpl : : RegisterPendingNodes ( )
{
FScopeLock ScopeLock ( & LazyInitCommandCritSection ) ;
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Processing %i Metasounds Frontend Registration Requests. " ) , LazyInitCommands . Num ( ) ) ;
2021-03-30 18:22:10 -04:00
uint64 CurrentTime = FPlatformTime : : Cycles64 ( ) ;
for ( TUniqueFunction < void ( ) > & Command : LazyInitCommands )
{
Command ( ) ;
}
LazyInitCommands . Empty ( ) ;
uint64 CyclesUsed = FPlatformTime : : Cycles64 ( ) - CurrentTime ;
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Initializing Metasounds Frontend took %f seconds. " ) , FPlatformTime : : ToSeconds64 ( CyclesUsed ) ) ;
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-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:07:53 -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:07:53 -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:45:51 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateInputNode ( const FName & InDataType , Metasound : : FInputNodeConstructorParams & & InParams )
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s] " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > CreateInputNode ( MoveTemp ( InParams ) ) ;
2021-03-30 18:22:10 -04:00
}
else
{
return nullptr ;
}
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateVariableNode ( const FName & InDataType , Metasound : : FVariableNodeConstructorParams & & InParams )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s] " ) , * InDataType . ToString ( ) ) )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > CreateVariableNode ( MoveTemp ( InParams ) ) ;
2021-05-28 14:09:45 -04:00
}
else
{
return nullptr ;
}
}
2021-06-14 16:45:51 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateOutputNode ( const FName & InDataType , Metasound : : FOutputNodeConstructorParams & & InParams )
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s] " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > CreateOutputNode ( MoveTemp ( InParams ) ) ;
2021-03-30 18:22:10 -04:00
}
else
{
return nullptr ;
}
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
Metasound : : FLiteral FRegistryContainerImpl : : CreateLiteralFromUObject ( const FName & InDataType , UObject * InObject )
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s] " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( Audio : : IProxyDataPtr ProxyPtr = Entry - > CreateProxy ( InObject ) )
2021-04-05 15:12:47 -04:00
{
if ( InObject )
{
2021-06-14 16:45:51 -04:00
ensureAlwaysMsgf ( ProxyPtr . IsValid ( ) , TEXT ( " UObject failed to create a valid proxy. " ) ) ;
2021-04-05 15:12:47 -04:00
}
return Metasound : : FLiteral ( MoveTemp ( ProxyPtr ) ) ;
}
2021-03-30 18:22:10 -04:00
}
2021-04-05 15:12:47 -04:00
return Metasound : : FLiteral ( ) ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
Metasound : : FLiteral FRegistryContainerImpl : : CreateLiteralFromUObjectArray ( const FName & InDataType , TArray < UObject * > InObjectArray )
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s] " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
TArray < Audio : : IProxyDataPtr > ProxyArray ;
for ( UObject * InObject : InObjectArray )
{
2021-06-14 16:45:51 -04:00
Audio : : IProxyDataPtr ProxyPtr = Entry - > CreateProxy ( InObject ) ;
2021-04-06 19:04:26 -04:00
2021-03-30 18:22:10 -04:00
if ( InObject )
{
ensureAlwaysMsgf ( ProxyPtr . IsValid ( ) , TEXT ( " UObject failed to create a valid proxy! " ) ) ;
}
2021-04-06 19:04:26 -04:00
ProxyArray . Add ( MoveTemp ( ProxyPtr ) ) ;
2021-03-30 18:22:10 -04:00
}
return Metasound : : FLiteral ( MoveTemp ( ProxyArray ) ) ;
}
else
{
return Metasound : : FLiteral ( ) ;
}
2021-02-18 13:11:33 -04:00
}
2021-06-14 16:45:51 -04:00
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , FDefaultNodeConstructorParams & & InParams ) const
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
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:45:51 -04:00
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
2021-03-30 18:22:10 -04:00
}
2021-06-14 16:45:51 -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:45:51 -04:00
return Entry - > CreateNode ( MoveTemp ( InParams ) ) ;
2021-03-30 18:22:10 -04:00
}
2021-06-14 16:45:51 -04:00
return nullptr ;
}
TUniquePtr < Metasound : : INode > FRegistryContainerImpl : : CreateNode ( const FNodeRegistryKey & InKey , const Metasound : : FNodeInitData & InInitData ) const
{
const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find node [RegistryKey:%s] " ) , * InKey ) )
{
return Entry - > CreateNode ( InInitData ) ;
}
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
Metasound : : ELiteralType FRegistryContainerImpl : : GetDesiredLiteralTypeForDataType ( FName InDataType ) const
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( nullptr = = Entry )
2021-03-30 18:22:10 -04:00
{
return Metasound : : ELiteralType : : Invalid ;
}
2021-06-14 16:45:51 -04:00
const FDataTypeRegistryInfo & Info = Entry - > GetDataTypeInfo ( ) ;
2021-03-30 18:22:10 -04:00
// If there's a designated preferred literal type for this datatype, use that.
2021-06-14 16:45:51 -04:00
if ( Info . PreferredLiteralType ! = Metasound : : ELiteralType : : Invalid )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Info . PreferredLiteralType ;
2021-03-30 18:22:10 -04:00
}
// Otherwise, we opt for the highest precision construction option available.
2021-06-14 16:45:51 -04:00
return Metasound : : Frontend : : MetasoundFrontendRegistryPrivate : : GetMostDescriptiveLiteralForDataType ( Info ) ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
UClass * FRegistryContainerImpl : : GetLiteralUClassForDataType ( FName InDataType ) const
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s]. " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > GetDataTypeInfo ( ) . ProxyGeneratorClass ;
2021-03-30 18:22:10 -04:00
}
2021-06-14 16:45:51 -04:00
return nullptr ;
2021-02-18 13:11:33 -04:00
}
2021-03-30 18:22:10 -04:00
bool FRegistryContainerImpl : : DoesDataTypeSupportLiteralType ( FName InDataType , Metasound : : ELiteralType InLiteralType ) const
2021-02-18 13:11:33 -04:00
{
2021-06-14 16:45:51 -04:00
const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) ;
if ( ensureAlwaysMsgf ( nullptr ! = Entry , TEXT ( " Could not find data type [Name:%s]. " ) , * InDataType . ToString ( ) ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
const FDataTypeRegistryInfo & Info = Entry - > GetDataTypeInfo ( ) ;
switch ( InLiteralType )
{
case Metasound : : ELiteralType : : Boolean :
{
return Info . bIsBoolParsable ;
}
case Metasound : : ELiteralType : : BooleanArray :
{
return Info . bIsBoolArrayParsable ;
}
case Metasound : : ELiteralType : : Integer :
{
return Info . bIsIntParsable ;
}
case Metasound : : ELiteralType : : IntegerArray :
{
return Info . bIsIntArrayParsable ;
}
case Metasound : : ELiteralType : : Float :
{
return Info . bIsFloatParsable ;
}
case Metasound : : ELiteralType : : FloatArray :
{
return Info . bIsFloatArrayParsable ;
}
case Metasound : : ELiteralType : : String :
{
return Info . bIsStringParsable ;
}
case Metasound : : ELiteralType : : StringArray :
{
return Info . bIsStringArrayParsable ;
}
case Metasound : : ELiteralType : : UObjectProxy :
{
return Info . bIsProxyParsable ;
}
case Metasound : : ELiteralType : : UObjectProxyArray :
{
return Info . bIsProxyArrayParsable ;
}
case Metasound : : ELiteralType : : None :
{
return Info . bIsDefaultParsable ;
}
case Metasound : : ELiteralType : : NoneArray :
{
return Info . bIsDefaultArrayParsable ;
}
case Metasound : : ELiteralType : : Invalid :
default :
{
static_assert ( static_cast < int32 > ( Metasound : : ELiteralType : : COUNT ) = = 13 , " Possible missing case coverage for ELiteralType " ) ;
return false ;
}
}
2021-03-30 18:22:10 -04:00
}
return false ;
}
2021-06-14 16:45:51 -04:00
bool FRegistryContainerImpl : : RegisterDataType ( const FName & InName , TUniquePtr < IDataTypeRegistryEntry > & & InRegistryEntry )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( InRegistryEntry . IsValid ( ) )
{
if ( ! ensureAlwaysMsgf ( ! RegisteredDataTypes . Contains ( InName ) ,
TEXT ( " Name collision when trying to register Metasound Data Type [Name:%s]. DataType must have "
" unique name and REGISTER_METASOUND_DATATYPE cannot be called in a public header. " ) ,
* InName . ToString ( ) ) )
{
return false ;
}
2021-03-30 18:22:10 -04:00
2021-06-14 16:45:51 -04:00
RegisteredDataTypes . Add ( InName , InRegistryEntry - > Clone ( ) ) ;
RegisterNode ( MakeUnique < FInputNodeRegistryEntry > ( InRegistryEntry - > Clone ( ) ) ) ;
RegisterNode ( MakeUnique < FOutputNodeRegistryEntry > ( InRegistryEntry - > Clone ( ) ) ) ;
RegisterNode ( MakeUnique < FVariableNodeRegistryEntry > ( MoveTemp ( InRegistryEntry ) ) ) ;
UE_LOG ( LogMetaSound , Verbose , TEXT ( " Registered Metasound Datatype [Name:%s]. " ) , * InName . ToString ( ) ) ;
return true ;
}
return false ;
}
FNodeRegistryKey FRegistryContainerImpl : : RegisterNode ( TUniquePtr < INodeRegistryEntry > & & InEntry )
{
2021-03-30 18:22:10 -04:00
FNodeRegistryKey Key ;
2021-06-14 16:45:51 -04:00
if ( InEntry . IsValid ( ) )
2021-03-30 18:22:10 -04:00
{
2021-07-12 16:12:36 -04:00
Key = NodeRegistryKey : : CreateKey ( InEntry - > GetClassInfo ( ) ) ;
2021-06-14 16:45:51 -04:00
2021-03-30 18:22:10 -04:00
// check to see if an identical node was already registered, and log
2021-05-03 17:52:04 -04:00
ensureAlwaysMsgf (
2021-06-14 16:45:51 -04:00
! RegisteredNodes . Contains ( Key ) ,
2021-06-08 10:52:31 -04:00
TEXT ( " Node with registry key already registered. "
2021-05-03 17:52:04 -04:00
" 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. " ) ,
2021-06-08 10:52:31 -04:00
* 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:07:53 -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:45:51 -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:45:51 -04:00
bool FRegistryContainerImpl : : UnregisterNode ( const FNodeRegistryKey & InKey )
2021-06-08 10:52:31 -04:00
{
if ( IsValidNodeRegistryKey ( InKey ) )
{
2021-06-14 16:45:51 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-06-08 10:52:31 -04:00
{
2021-06-23 20:07:53 -04:00
RegistryTransactionHistory . Add ( FNodeRegistryTransaction ( FNodeRegistryTransaction : : ETransactionType : : NodeUnregistration , InKey , Entry - > GetClassInfo ( ) ) ) ;
2021-06-08 10:52:31 -04:00
2021-06-14 16:45:51 -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:45:51 -04:00
return RegisteredNodes . Contains ( InKey ) ;
2021-03-30 18:22:10 -04:00
}
TArray < FName > FRegistryContainerImpl : : GetAllValidDataTypes ( )
{
TArray < FName > OutDataTypes ;
2021-06-14 16:45:51 -04:00
for ( auto & DataTypeTuple : RegisteredDataTypes )
2021-03-30 18:22:10 -04:00
{
OutDataTypes . Add ( DataTypeTuple . Key ) ;
}
return OutDataTypes ;
}
2021-06-14 16:45:51 -04:00
bool FRegistryContainerImpl : : GetInfoForDataType ( FName InDataType , Metasound : : Frontend : : FDataTypeRegistryInfo & OutInfo )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
OutInfo = Entry - > GetDataTypeInfo ( ) ;
2021-03-30 18:22:10 -04:00
return true ;
}
2021-06-14 16:45:51 -04:00
return false ;
2021-03-30 18:22:10 -04:00
}
2021-06-14 16:45:51 -04:00
TSharedPtr < const Metasound : : Frontend : : IEnumDataTypeInterface > FRegistryContainerImpl : : GetEnumInterfaceForDataType ( FName InDataType ) const
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > GetEnumInterface ( ) ;
2021-03-30 18:22:10 -04:00
}
return nullptr ;
}
TSharedPtr < Metasound : : IDataChannel , ESPMode : : ThreadSafe > FRegistryContainerImpl : : CreateDataChannelForDataType ( const FName & InDataType , const Metasound : : FOperatorSettings & InSettings ) const
{
2021-06-14 16:45:51 -04:00
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataType ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
return Entry - > CreateDataChannel ( InSettings ) ;
2021-03-30 18:22:10 -04:00
}
return nullptr ;
}
2021-06-14 16:45:51 -04:00
bool FRegistryContainerImpl : : FindFrontendClassFromRegistered ( const FNodeRegistryKey & InKey , FMetasoundFrontendClass & OutClass )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
OutClass = Entry - > GetFrontendClass ( ) ;
2021-05-28 14:09:45 -04:00
return true ;
}
return false ;
}
2021-06-14 16:45:51 -04:00
bool FRegistryContainerImpl : : FindNodeClassInfoFromRegistered ( const Metasound : : Frontend : : FNodeRegistryKey & InKey , FNodeClassInfo & OutInfo )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:45:51 -04:00
if ( const INodeRegistryEntry * Entry = FindNodeEntry ( InKey ) )
2021-05-28 14:09:45 -04:00
{
2021-06-14 16:45:51 -04:00
OutInfo = Entry - > GetClassInfo ( ) ;
return true ;
}
return false ;
}
bool FRegistryContainerImpl : : FindInputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataTypeName ) )
{
2021-07-12 16:12:36 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Entry - > GetFrontendInputClass ( ) . Metadata ) ;
2021-03-30 18:22:10 -04:00
return true ;
}
return false ;
}
2021-06-14 16:45:51 -04:00
bool FRegistryContainerImpl : : FindVariableNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
2021-03-30 18:22:10 -04:00
{
2021-06-14 16:45:51 -04:00
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataTypeName ) )
2021-03-30 18:22:10 -04:00
{
2021-07-12 16:12:36 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Entry - > GetFrontendVariableClass ( ) . Metadata ) ;
2021-06-14 16:45:51 -04:00
return true ;
}
return false ;
}
bool FRegistryContainerImpl : : FindOutputNodeRegistryKeyForDataType ( const FName & InDataTypeName , FNodeRegistryKey & OutKey )
{
if ( const IDataTypeRegistryEntry * Entry = FindDataTypeEntry ( InDataTypeName ) )
{
2021-07-12 16:12:36 -04:00
OutKey = NodeRegistryKey : : CreateKey ( Entry - > GetFrontendOutputClass ( ) . 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:45:51 -04:00
auto WrappedFunc = [ & ] ( const TPair < FNodeRegistryKey , TUniquePtr < INodeRegistryEntry > > & Pair )
2021-05-03 17:52:04 -04:00
{
2021-06-14 16:45:51 -04:00
InIterFunc ( Pair . Value - > GetFrontendClass ( ) ) ;
2021-05-03 17:52:04 -04:00
} ;
2021-06-14 16:45:51 -04:00
if ( EMetasoundFrontendClassType : : Invalid = = InClassType )
2021-05-03 17:52:04 -04:00
{
2021-06-14 16:45:51 -04:00
// Iterate through all classes.
Algo : : ForEach ( RegisteredNodes , WrappedFunc ) ;
2021-05-03 17:52:04 -04:00
}
2021-06-14 16:45:51 -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 IDataTypeRegistryEntry * FRegistryContainerImpl : : FindDataTypeEntry ( const FName & InDataTypeName ) const
{
if ( const TUniquePtr < IDataTypeRegistryEntry > * Entry = RegisteredDataTypes . Find ( InDataTypeName ) )
{
if ( Entry - > IsValid ( ) )
{
return Entry - > Get ( ) ;
}
}
return nullptr ;
}
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:17:31 -04:00
} // namespace MetasoundFrontendRegistriesPrivate
2021-06-08 10:52:31 -04:00
2021-06-23 20:07:53 -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:12:36 -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 )
{
if ( InLHS . ClassName = = InRHS . ClassName )
{
if ( InLHS . Type = = InRHS . Type )
{
if ( InLHS . Version = = InRHS . Version )
{
return true ;
}
}
}
return false ;
}
bool IsEqual ( const FNodeClassInfo & InLHS , const FMetasoundFrontendClassMetadata & InRHS )
{
if ( InLHS . ClassName = = InRHS . ClassName )
{
if ( InLHS . Type = = InRHS . Type )
{
if ( InLHS . Version = = InRHS . Version )
{
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 )
{
return CreateKey ( InNodeMetadata . Type , InNodeMetadata . ClassName . GetFullName ( ) . ToString ( ) , InNodeMetadata . Version . Major , InNodeMetadata . Version . Minor ) ;
}
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:12:36 -04:00
return NodeRegistryKey : : IsValid ( InKey ) ;
2021-06-08 10:52:31 -04:00
}
2021-06-14 16:45:51 -04:00
FNodeClassInfo : : FNodeClassInfo ( const FMetasoundFrontendClassMetadata & InMetadata )
2021-06-16 11:20:44 -04:00
: ClassName ( InMetadata . ClassName )
, Type ( InMetadata . Type )
, Version ( InMetadata . Version )
2021-06-14 16:45:51 -04:00
{
}
2021-06-16 11:20:44 -04:00
FNodeClassInfo : : FNodeClassInfo ( const FMetasoundFrontendGraphClass & InClass , FName InAssetPath )
: ClassName ( InClass . Metadata . ClassName )
, Type ( EMetasoundFrontendClassType : : External ) // Overridden as it is considered the same as an external class in the registry
, AssetClassID ( FGuid ( ClassName . Name . ToString ( ) ) )
, AssetPath ( InAssetPath )
, Version ( InClass . Metadata . Version )
2021-06-14 16:45:51 -04:00
{
2021-06-16 11:20:44 -04:00
ensure ( ! AssetPath . IsNone ( ) ) ;
2021-06-14 16:45:51 -04:00
2021-06-16 11:20:44 -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:45:51 -04:00
}
2021-06-09 18:17:31 -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:12:36 -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:12:36 -04:00
return Metasound : : Frontend : : NodeRegistryKey : : CreateKey ( InNodeMetadata ) ;
2021-01-13 10:48:59 -04:00
}
2021-06-14 16:45:51 -04:00
Metasound : : Frontend : : FNodeRegistryKey FMetasoundFrontendRegistryContainer : : GetRegistryKey ( const FNodeClassInfo & InClassInfo )
{
2021-07-12 16:12:36 -04:00
return Metasound : : Frontend : : NodeRegistryKey : : CreateKey ( InClassInfo ) ;
2021-06-14 16:45:51 -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:45:51 -04:00
return Registry - > FindFrontendClassFromRegistered ( InKey , OutClass ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-06-14 16:45:51 -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:45:51 -04:00
return Registry - > FindNodeClassInfoFromRegistered ( InKey , OutInfo ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-06-14 16:45:51 -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:45:51 -04:00
return Registry - > FindInputNodeRegistryKeyForDataType ( InDataTypeName , OutKey ) ;
2021-05-28 14:09:45 -04:00
}
return false ;
}
2021-06-14 16:45:51 -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:45:51 -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 ;
}