2020-08-26 14:16:05 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "CoreMinimal.h"
# include "MetasoundBuilderInterface.h"
2020-10-26 13:39:01 -04:00
# include "MetasoundBuildError.h"
2020-11-24 15:24:29 -04:00
# include "MetasoundNode.h"
2020-08-26 14:16:05 -04:00
# include "MetasoundNodeInterface.h"
# include "MetasoundOperatorInterface.h"
2020-11-04 14:26:37 -04:00
# include "MetasoundDataFactory.h"
2020-08-26 14:16:05 -04:00
# include "MetasoundDataReference.h"
# include "MetasoundExecutableOperator.h"
2021-01-23 12:59:01 -04:00
# include "MetasoundFrontend.h"
2020-08-26 14:16:05 -04:00
# include <type_traits>
2020-11-24 15:24:29 -04:00
# define LOCTEXT_NAMESPACE "MetasoundFrontend"
2020-08-26 14:16:05 -04:00
namespace Metasound
{
// This convenience node can be registered and will invoke static_cast<ToDataType>(FromDataType) every time it is executed.
template < typename FromDataType , typename ToDataType >
2020-11-24 15:24:29 -04:00
class TAutoConverterNode : public FNode
2020-08-26 14:16:05 -04:00
{
static_assert ( std : : is_convertible < FromDataType , ToDataType > : : value , " Tried to create an auto converter node between two types we can't static_cast between. " ) ;
public :
2020-11-04 14:26:37 -04:00
static const FString & GetInputName ( )
2020-08-26 14:16:05 -04:00
{
2020-11-04 14:26:37 -04:00
static const FString InputName = GetMetasoundDataTypeString < FromDataType > ( ) ;
2020-08-26 14:16:05 -04:00
return InputName ;
}
2020-11-04 14:26:37 -04:00
static const FString & GetOutputName ( )
2020-08-26 14:16:05 -04:00
{
2020-11-04 14:26:37 -04:00
static const FString OutputName = GetMetasoundDataTypeString < ToDataType > ( ) ;
2020-08-26 14:16:05 -04:00
return OutputName ;
}
2020-11-24 15:24:29 -04:00
static FVertexInterface DeclareVertexInterface ( )
{
return FVertexInterface (
FInputVertexInterface (
TInputDataVertexModel < FromDataType > ( GetInputName ( ) , FText : : GetEmpty ( ) )
) ,
FOutputVertexInterface (
TOutputDataVertexModel < ToDataType > ( GetOutputName ( ) , FText : : GetEmpty ( ) )
)
) ;
}
2021-01-28 19:02:51 -04:00
static const FNodeClassMetadata & GetAutoConverterNodeMetadata ( )
2020-11-24 15:24:29 -04:00
{
2021-01-28 19:02:51 -04:00
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
2020-11-24 15:24:29 -04:00
{
2021-01-23 12:59:01 -04:00
const FString & InputDisplayName = GetInputName ( ) ;
const FString & OutputDisplayName = GetOutputName ( ) ;
FNodeDisplayStyle DisplayStyle ;
DisplayStyle . bShowName = false ;
DisplayStyle . bShowInputNames = false ;
DisplayStyle . bShowOutputNames = false ;
2021-01-28 19:02:51 -04:00
FNodeClassMetadata Info ;
2021-02-08 15:58:01 -04:00
Info . ClassName = { TEXT ( " Convert " ) , GetMetasoundDataTypeName < ToDataType > ( ) , GetMetasoundDataTypeName < FromDataType > ( ) } ;
2020-11-24 15:24:29 -04:00
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
2021-02-08 15:58:01 -04:00
Info . DisplayName = FText : : Format ( LOCTEXT ( " Metasound_AutoConverterNodeDisplayNameFormat " , " {0} to {1} " ) , FText : : FromName ( GetMetasoundDataTypeName < FromDataType > ( ) ) , FText : : FromName ( GetMetasoundDataTypeName < ToDataType > ( ) ) ) ;
2020-11-24 15:24:29 -04:00
Info . Description = LOCTEXT ( " Metasound_ConverterNodeDescription " , " Converts between two different data types. " ) ;
Info . Author = PluginAuthor ;
2021-01-23 12:59:01 -04:00
Info . DisplayStyle = DisplayStyle ;
2020-11-24 15:24:29 -04:00
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = DeclareVertexInterface ( ) ;
2021-01-20 00:42:47 -04:00
Info . CategoryHierarchy = { LOCTEXT ( " Metasound_ConvertNodeCategory " , " Conversions " ) } ;
2021-01-23 12:59:01 -04:00
Info . Keywords = { " Convert " , GetMetasoundDataTypeName < FromDataType > ( ) , GetMetasoundDataTypeName < ToDataType > ( ) } ;
2020-11-24 15:24:29 -04:00
return Info ;
} ;
2021-01-28 19:02:51 -04:00
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
2020-11-24 15:24:29 -04:00
return Info ;
}
2020-08-26 14:16:05 -04:00
private :
2020-10-26 13:39:01 -04:00
/** FConverterOperator converts from "FromDataType" to "ToDataType" using
* a implicit conversion operators .
*/
2020-08-26 14:16:05 -04:00
class FConverterOperator : public TExecutableOperator < FConverterOperator >
{
public :
2020-10-26 13:39:01 -04:00
FConverterOperator ( TDataReadReference < FromDataType > InFromDataReference , TDataWriteReference < ToDataType > InToDataReference )
2020-08-26 14:16:05 -04:00
: FromData ( InFromDataReference )
2020-10-26 13:39:01 -04:00
, ToData ( InToDataReference )
2020-08-26 14:16:05 -04:00
{
}
virtual ~ FConverterOperator ( ) { }
2020-12-08 19:34:18 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override
2020-08-26 14:16:05 -04:00
{
2020-12-08 19:34:18 -04:00
FDataReferenceCollection Inputs ;
2021-01-23 12:59:01 -04:00
Inputs . AddDataReadReference < FromDataType > ( GetInputName ( ) , FromData ) ;
2020-08-26 14:16:05 -04:00
return Inputs ;
}
2020-12-08 19:34:18 -04:00
virtual FDataReferenceCollection GetOutputs ( ) const override
2020-08-26 14:16:05 -04:00
{
2020-12-08 19:34:18 -04:00
FDataReferenceCollection Outputs ;
Outputs . AddDataReadReference < ToDataType > ( GetOutputName ( ) , ToData ) ;
2020-08-26 14:16:05 -04:00
return Outputs ;
}
void Execute ( )
{
* ToData = static_cast < ToDataType > ( * FromData ) ;
}
private :
TDataReadReference < FromDataType > FromData ;
TDataWriteReference < ToDataType > ToData ;
} ;
2020-10-26 13:39:01 -04:00
/** FConverterOperatorFactory creates an operator which converts from
* " FromDataType " to " ToDataType " .
*/
2020-08-26 14:16:05 -04:00
class FCoverterOperatorFactory : public IOperatorFactory
{
public :
FCoverterOperatorFactory ( ) = default ;
virtual TUniquePtr < IOperator > CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors ) override
{
2020-11-04 14:26:37 -04:00
TDataWriteReference < ToDataType > WriteReference = TDataWriteReferenceFactory < ToDataType > : : CreateAny ( InParams . OperatorSettings ) ;
2020-10-26 13:39:01 -04:00
2020-08-26 14:16:05 -04:00
if ( ! InParams . InputDataReferences . ContainsDataReadReference < FromDataType > ( GetInputName ( ) ) )
{
2020-10-26 13:39:01 -04:00
if ( ensure ( InParams . Node . GetVertexInterface ( ) . ContainsInputVertex ( GetInputName ( ) ) ) )
{
// There should be something hooked up to the converter node. Report it as an error.
FInputDataDestination Dest ( InParams . Node , InParams . Node . GetVertexInterface ( ) . GetInputVertex ( GetInputName ( ) ) ) ;
AddBuildError < FMissingInputDataReferenceError > ( OutErrors , Dest ) ;
}
// We can still build something even though there is an error.
2020-11-04 14:26:37 -04:00
TDataReadReference < FromDataType > ReadReference = TDataReadReferenceFactory < FromDataType > : : CreateAny ( InParams . OperatorSettings ) ;
2020-10-26 13:39:01 -04:00
return MakeUnique < FConverterOperator > ( ReadReference , WriteReference ) ;
2020-08-26 14:16:05 -04:00
}
2020-10-26 13:39:01 -04:00
TDataReadReference < FromDataType > ReadReference = InParams . InputDataReferences . GetDataReadReference < FromDataType > ( GetInputName ( ) ) ;
return MakeUnique < FConverterOperator > ( ReadReference , WriteReference ) ;
2020-08-26 14:16:05 -04:00
}
} ;
public :
TAutoConverterNode ( const FNodeInitData & InInitData )
2021-01-28 19:02:51 -04:00
: FNode ( InInitData . InstanceName , InInitData . InstanceID , GetAutoConverterNodeMetadata ( ) )
2020-08-26 14:16:05 -04:00
, Interface ( DeclareVertexInterface ( ) )
, Factory ( MakeOperatorFactoryRef < FCoverterOperatorFactory > ( ) )
{
}
virtual ~ TAutoConverterNode ( ) = default ;
virtual const FVertexInterface & GetVertexInterface ( ) const override
{
return Interface ;
}
virtual bool SetVertexInterface ( const FVertexInterface & InInterface ) override
{
return Interface = = InInterface ;
}
virtual bool IsVertexInterfaceSupported ( const FVertexInterface & InInterface ) const override
{
return Interface = = InInterface ;
}
virtual FOperatorFactorySharedRef GetDefaultOperatorFactory ( ) const override
{
return Factory ;
}
private :
FVertexInterface Interface ;
FOperatorFactorySharedRef Factory ;
} ;
}
# undef LOCTEXT_NAMESPACE