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-08-26 14:16:05 -04:00
# include "MetasoundNodeInterface.h"
# include "MetasoundOperatorInterface.h"
# include "MetasoundDataReference.h"
# include "MetasoundExecutableOperator.h"
# include <type_traits>
# define LOCTEXT_NAMESPACE "MetasoundGraphCore"
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 >
class TAutoConverterNode : public INode
{
static_assert ( TDataReferenceTypeInfo < FromDataType > : : bIsValidSpecialization , " Please use DECLARE_METASOUND_DATA_REFERENCE_TYPES with this class before trying to create an converter node with it. " ) ;
static_assert ( TDataReferenceTypeInfo < ToDataType > : : bIsValidSpecialization , " Please use DECLARE_METASOUND_DATA_REFERENCE_TYPES with this class before trying to create an converter node with it. " ) ;
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 :
static FString & GetInputName ( )
{
static FString InputName = FString ( TDataReferenceTypeInfo < FromDataType > : : TypeName ) ;
return InputName ;
}
static FString & GetOutputName ( )
{
static FString OutputName = FString ( TDataReferenceTypeInfo < ToDataType > : : TypeName ) ;
return OutputName ;
}
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
{
2020-10-26 13:39:01 -04:00
Outputs . AddDataReadReference < ToDataType > ( GetOutputName ( ) , ToData ) ;
2020-08-26 14:16:05 -04:00
}
virtual ~ FConverterOperator ( ) { }
virtual const FDataReferenceCollection & GetInputs ( ) const override
{
return Inputs ;
}
virtual const FDataReferenceCollection & GetOutputs ( ) const override
{
return Outputs ;
}
void Execute ( )
{
* ToData = static_cast < ToDataType > ( * FromData ) ;
}
private :
TDataReadReference < FromDataType > FromData ;
TDataWriteReference < ToDataType > ToData ;
FDataReferenceCollection Inputs ;
FDataReferenceCollection Outputs ;
} ;
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-10-26 13:39:01 -04:00
TDataWriteReference < ToDataType > WriteReference = TDataReferenceFactory < ToDataType > : : CreateNewWriteReference ( InParams . OperatorSettings ) ;
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.
TDataReadReference < FromDataType > ReadReference = TDataReferenceFactory < FromDataType > : : CreateNewReadReference ( InParams . OperatorSettings ) ;
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 :
static FVertexInterface DeclareVertexInterface ( )
{
return FVertexInterface (
FInputVertexInterface (
TInputDataVertexModel < FromDataType > ( GetInputName ( ) , FText : : GetEmpty ( ) )
) ,
FOutputVertexInterface (
TOutputDataVertexModel < ToDataType > ( GetOutputName ( ) , FText : : GetEmpty ( ) )
)
) ;
}
TAutoConverterNode ( const FNodeInitData & InInitData )
: NodeDescription ( InInitData . InstanceName )
, Interface ( DeclareVertexInterface ( ) )
, Factory ( MakeOperatorFactoryRef < FCoverterOperatorFactory > ( ) )
{
}
virtual ~ TAutoConverterNode ( ) = default ;
virtual const FName & GetClassName ( ) const override
{
static const FName ClassName ( * FString : : Printf ( TEXT ( " %s To %s " ) , * GetInputName ( ) , * GetOutputName ( ) ) ) ;
return ClassName ;
}
virtual const FString & GetInstanceName ( ) const override
{
return NodeDescription ;
}
virtual const FText & GetDescription ( ) const override
{
static const FText Description = LOCTEXT ( " Metasound_ConverterNodeDescription " , " Converts between two different data types. " ) ;
return Description ;
}
virtual const FText & GetAuthorName ( ) const override
{
return PluginAuthor ;
}
virtual const FText & GetPromptIfMissing ( ) const override
{
return PluginNodeMissingPrompt ;
}
virtual const FVertexInterface & GetVertexInterface ( ) const override
{
return Interface ;
}
virtual const FVertexInterface & GetDefaultVertexInterface ( ) 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 :
FString NodeDescription ;
FVertexInterface Interface ;
FOperatorFactorySharedRef Factory ;
} ;
}
# undef LOCTEXT_NAMESPACE