2020-05-22 23:46:09 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
2020-07-22 14:52:03 -04:00
# include "Internationalization/Text.h"
2022-06-02 10:50:07 -04:00
# include "MetasoundBuilderInterface.h"
2021-05-20 19:33:21 -04:00
# include "MetasoundDataReference.h"
2022-06-02 10:50:07 -04:00
# include "MetasoundFrontendDataTypeTraits.h"
# include "MetasoundLiteral.h"
# include "MetasoundNode.h"
2020-05-22 23:46:09 -04:00
# include "MetasoundNodeInterface.h"
2022-06-02 10:50:07 -04:00
# include "MetasoundNodeRegistrationMacro.h"
2021-05-28 14:09:45 -04:00
# include "MetasoundOperatorInterface.h"
2021-03-23 17:55:31 -04:00
# include "MetasoundTrigger.h"
2022-06-02 10:50:07 -04:00
# include "MetasoundVertexData.h"
# include "UObject/NameTypes.h"
2020-05-22 23:46:09 -04:00
2021-05-28 14:09:45 -04:00
# define LOCTEXT_NAMESPACE "MetasoundFrontend"
2020-07-22 14:52:03 -04:00
2020-05-22 23:46:09 -04:00
namespace Metasound
{
2021-05-28 14:09:45 -04:00
/** A writable input and a readable output. */
2020-11-04 14:26:37 -04:00
template < typename DataType >
class TInputOperator : public IOperator
{
public :
using FDataWriteReference = TDataWriteReference < DataType > ;
2021-09-13 14:13:39 -04:00
TInputOperator ( const FVertexName & InDataReferenceName , FDataWriteReference InDataReference )
2021-03-23 17:55:31 -04:00
: DataReferenceName ( InDataReferenceName )
// Executable DataTypes require a copy of the output to operate on whereas non-executable
// types do not. Avoid copy by assigning to reference for non-executable types.
2021-03-23 22:43:28 -04:00
, InputValue ( InDataReference )
, OutputValue ( TExecutableDataType < DataType > : : bIsExecutable ? FDataWriteReference : : CreateNew ( * InDataReference ) : InDataReference )
2020-11-04 14:26:37 -04:00
{
}
2021-05-20 19:33:21 -04:00
virtual ~ TInputOperator ( ) = default ;
2020-11-04 14:26:37 -04:00
2020-12-08 19:34:18 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override
2022-06-02 10:50:07 -04:00
{
// This is slated to be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
}
virtual FDataReferenceCollection GetOutputs ( ) const override
{
// This is slated to be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
}
virtual void Bind ( FVertexInterfaceData & InOutVertexData ) const override
2020-11-04 14:26:37 -04:00
{
2021-05-20 19:33:21 -04:00
// TODO: Expose a readable reference instead of a writable reference.
//
// If data needs to be written to, outside entities should create
// it and pass it in as a readable reference. Currently, the workflow
// is to have the input node create a writable reference which is then
// queried by the outside world. Exposing writable references causes
// code maintainability issues where TInputNode<> specializations need
// to handle multiple situations which can happen in an input node.
//
// The only reason that this code is not removed immediately is because
// of the `TExecutableDataType<>` which primarily supports the FTrigger.
// The TExecutableDataType<> advances the trigger within the graph. But,
// with graph composition, the owner of the data type becomes more
// complicated and hence triggers advancing should be managed by a
// different object. Preferably the graph operator itself, or an
// explicit trigger manager tied to the environment.
2022-06-02 10:50:07 -04:00
InOutVertexData . GetInputs ( ) . BindWriteVertex ( DataReferenceName , InputValue ) ;
2020-11-04 14:26:37 -04:00
2022-06-02 10:50:07 -04:00
InOutVertexData . GetOutputs ( ) . BindReadVertex ( DataReferenceName , OutputValue ) ;
2020-11-04 14:26:37 -04:00
}
2021-03-23 17:55:31 -04:00
void Execute ( )
{
2021-03-23 22:43:28 -04:00
TExecutableDataType < DataType > : : Execute ( * InputValue , * OutputValue ) ;
2021-03-23 17:55:31 -04:00
}
2021-05-20 19:33:21 -04:00
void ExecutPassThrough ( )
{
if ( TExecutableDataType < DataType > : : bIsExecutable )
{
* OutputValue = * InputValue ;
}
}
2021-03-23 17:55:31 -04:00
static void ExecuteFunction ( IOperator * InOperator )
{
static_cast < TInputOperator < DataType > * > ( InOperator ) - > Execute ( ) ;
}
2020-11-04 14:26:37 -04:00
virtual FExecuteFunction GetExecuteFunction ( ) override
{
2021-03-23 17:55:31 -04:00
if ( TExecutableDataType < DataType > : : bIsExecutable )
{
2021-09-07 17:06:42 -04:00
return & TInputOperator < DataType > : : ExecuteFunction ;
2021-03-23 17:55:31 -04:00
}
2020-11-04 14:26:37 -04:00
return nullptr ;
}
2021-05-28 14:09:45 -04:00
protected :
2021-09-13 14:13:39 -04:00
FVertexName DataReferenceName ;
2021-03-23 17:55:31 -04:00
2021-03-23 22:43:28 -04:00
FDataWriteReference InputValue ;
FDataWriteReference OutputValue ;
2020-11-04 14:26:37 -04:00
} ;
2021-05-20 19:33:21 -04:00
/** TPassThroughOperator supplies a readable input and a readable output.
*
* It does * not * invoke executable data types ( see ` TExecutableDataType < > ` ) .
2020-11-04 14:26:37 -04:00
*/
template < typename DataType >
2021-05-20 19:33:21 -04:00
class TPassThroughOperator : public TInputOperator < DataType >
{
public :
using FDataReadReference = TDataReadReference < DataType > ;
using Super = TInputOperator < DataType > ;
2021-09-13 14:13:39 -04:00
TPassThroughOperator ( const FVertexName & InDataReferenceName , FDataReadReference InDataReference )
2022-06-02 10:50:07 -04:00
: TInputOperator < DataType > ( InDataReferenceName , WriteCast ( InDataReference ) ) // Write cast is safe because `GetExecuteFunction() and Bind() are overridden, ensuring that data is not written.
2021-05-20 19:33:21 -04:00
, DataReferenceName ( InDataReferenceName )
{
}
virtual ~ TPassThroughOperator ( ) = default ;
2022-06-02 10:50:07 -04:00
virtual void Bind ( FVertexInterfaceData & InOutVertexData ) const override
2021-05-20 19:33:21 -04:00
{
2022-06-02 10:50:07 -04:00
InOutVertexData . GetInputs ( ) . BindReadVertex ( DataReferenceName , Super : : InputValue ) ;
InOutVertexData . GetOutputs ( ) . BindReadVertex ( DataReferenceName , Super : : OutputValue ) ;
2021-05-20 19:33:21 -04:00
}
static void ExecuteFunction ( IOperator * InOperator )
{
static_cast < TPassThroughOperator < DataType > * > ( InOperator ) - > ExecutPassThrough ( ) ;
}
virtual IOperator : : FExecuteFunction GetExecuteFunction ( ) override
{
// TODO: this is a hack until we can remove TExecutableOperator<>.
//
// The primary contention is that we would like to allow developers
// to specialize `TInputNode<>` as in `TInputNode<FStereoAudioFormat>`.
// `TExecutableOperator<>` adds in a level of complexity that makes it
// difficult to allow specialization of TInputNode and to derive from
// TInputNode to create the TPassThroughOperator. Particularly because
// TExecutableOperator<> alters which output data reference is used.
// Specializations of TInputNode also tend to alter the output data
// references. Supporting both is likely to cause issues.
//
// We may need to ensure that input nodes do not provide execution
// functions. Or we may need a more explicit way of only allowing
// outputs to be modified. Likely a mix of the `final` keyword
// and disabling template specialization of a base class.
//
// namespace Private
// {
// class TInputNodePrivate<>
// {
// GetInputs() final
// GetExecutionFunction() final
// GetOutputs()
// }
// }
//
// template<DataType>
// using TInputNodeBase<DataType> = TInputNodePrivate<DataType>; // Do not allow specialization of TInputNodePrivate<> or TInputNodeBase<> (this works because you can't specialize a template alias)
//
// // DO ALLOW specialization of TInputNode
// template<DataType>
// class TInputNode<DataType> : public TInputNodeBase<DataType>
// {
// };
//
// template<>
// class TInputNode<MyType> : public TInputNodeBase<MyType>
// {
// GetOutputs() <-- OK to override
// }
//
if ( TExecutableDataType < DataType > : : bIsExecutable )
{
return & TPassThroughOperator < DataType > : : ExecuteFunction ;
}
return nullptr ;
}
private :
2021-09-13 14:13:39 -04:00
FVertexName DataReferenceName ;
2021-05-20 19:33:21 -04:00
} ;
2022-06-02 10:50:07 -04:00
/** FInputValueOperator provides an input for value references. */
class METASOUNDFRONTEND_API FInputValueOperator : public IOperator
{
public :
/** Construct an FInputValueOperator with the name of the vertex and the
* value reference associated with input .
*/
template < typename DataType >
explicit FInputValueOperator ( const FName & InVertexName , const TDataValueReference < DataType > & InValueRef )
: VertexName ( InVertexName )
, Default ( InValueRef )
{
}
virtual ~ FInputValueOperator ( ) = default ;
virtual FDataReferenceCollection GetInputs ( ) const override ;
virtual FDataReferenceCollection GetOutputs ( ) const override ;
virtual void Bind ( FVertexInterfaceData & InVertexData ) const override ;
virtual FExecuteFunction GetExecuteFunction ( ) override ;
private :
FName VertexName ;
FAnyDataReference Default ;
} ;
2021-05-20 19:33:21 -04:00
/** Data type creation policy to create by copy construction. */
template < typename DataType >
2022-06-02 10:50:07 -04:00
struct UE_DEPRECATED ( 5.1 , " Moved to private implementation. " ) FCreateDataReferenceWithCopy
2021-05-20 19:33:21 -04:00
{
template < typename . . . ArgTypes >
FCreateDataReferenceWithCopy ( ArgTypes & & . . . Args )
: Data ( Forward < ArgTypes > ( Args ) . . . )
{
}
TDataWriteReference < DataType > CreateDataReference ( const FOperatorSettings & InOperatorSettings ) const
{
return TDataWriteReferenceFactory < DataType > : : CreateExplicitArgs ( InOperatorSettings , Data ) ;
}
private :
DataType Data ;
} ;
2022-06-02 10:50:07 -04:00
2021-05-20 19:33:21 -04:00
/** Data type creation policy to create by literal construction. */
template < typename DataType >
2022-06-02 10:50:07 -04:00
struct UE_DEPRECATED ( 5.1 , " Moved to private implementation. " ) FCreateDataReferenceWithLiteral
2021-05-20 19:33:21 -04:00
{
// If the data type is parsable from a literal type, then the data type
// can be registered as an input type with the frontend. To make a
// DataType registrable, either create a constructor for the data type
// which accepts the one of the supported literal types with an optional
// FOperatorSettings argument, or create a default constructor, or specialize
// this factory with an implementation for that specific data type.
static constexpr bool bCanCreateWithLiteral = TLiteralTraits < DataType > : : bIsParsableFromAnyLiteralType ;
FCreateDataReferenceWithLiteral ( FLiteral & & InLiteral )
: Literal ( MoveTemp ( InLiteral ) )
{
}
TDataWriteReference < DataType > CreateDataReference ( const FOperatorSettings & InOperatorSettings ) const
{
return TDataWriteReferenceLiteralFactory < DataType > : : CreateExplicitArgs ( InOperatorSettings , Literal ) ;
}
private :
FLiteral Literal ;
} ;
/** TInputOperatorFactory initializes the DataType at construction. It uses
* the ReferenceCreatorType to create a data reference if one is not passed in .
*/
template < typename DataType , typename ReferenceCreatorType >
2022-06-02 10:50:07 -04:00
class UE_DEPRECATED ( 5.1 , " Moved to private implementation " ) TInputOperatorFactory : public IOperatorFactory
2020-11-04 14:26:37 -04:00
{
public :
using FDataWriteReference = TDataWriteReference < DataType > ;
2021-05-20 19:33:21 -04:00
using FDataReadReference = TDataReadReference < DataType > ;
2020-11-04 14:26:37 -04:00
2021-05-20 19:33:21 -04:00
TInputOperatorFactory ( ReferenceCreatorType & & InReferenceCreator )
: ReferenceCreator ( MoveTemp ( InReferenceCreator ) )
2020-11-04 14:26:37 -04:00
{
}
2022-05-19 14:18:38 -04:00
virtual TUniquePtr < IOperator > CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults ) override ;
2020-11-04 14:26:37 -04:00
private :
2021-05-20 19:33:21 -04:00
ReferenceCreatorType ReferenceCreator ;
2020-11-04 14:26:37 -04:00
} ;
/** TInputNode represents an input to a metasound graph. */
2022-06-02 10:50:07 -04:00
template < typename DataType , EVertexAccessType VertexAccess = EVertexAccessType : : Reference >
2020-08-24 10:57:03 -04:00
class TInputNode : public FNode
2020-05-22 23:46:09 -04:00
{
2022-06-02 10:50:07 -04:00
static constexpr bool bIsConstructorInput = VertexAccess = = EVertexAccessType : : Value ;
static constexpr bool bIsSupportedConstructorInput = TIsConstructorVertexSupported < DataType > : : Value & & bIsConstructorInput ;
static constexpr bool bIsReferenceInput = VertexAccess = = EVertexAccessType : : Reference ;
static constexpr bool bIsSupportedReferenceInput = TLiteralTraits < DataType > : : bIsParsableFromAnyLiteralType & & bIsReferenceInput ;
static constexpr bool bIsSupportedInput = bIsSupportedConstructorInput | | bIsSupportedReferenceInput ;
// Use Variant names to differentiate between normal input nodes and constructor
// input nodes.
static FName GetVariantName ( )
{
if constexpr ( EVertexAccessType : : Value = = VertexAccess )
{
return FName ( " Constructor " ) ;
}
else
{
return FName ( ) ;
}
}
// Factory for creating input operators.
class FInputNodeOperatorFactory : public IOperatorFactory
{
static constexpr bool bIsReferenceVertexAccess = VertexAccess = = EVertexAccessType : : Reference ;
static constexpr bool bIsValueVertexAccess = VertexAccess = = EVertexAccessType : : Value ;
static_assert ( bIsValueVertexAccess | | bIsReferenceVertexAccess , " Unsupported EVertexAccessType " ) ;
// Choose which data reference type is created based on template parameters
using FDataReference = std : : conditional_t < bIsReferenceVertexAccess , TDataWriteReference < DataType > , TDataValueReference < DataType > > ;
using FPassThroughDataReference = std : : conditional_t < bIsReferenceVertexAccess , TDataReadReference < DataType > , TDataValueReference < DataType > > ;
// Utility struct for creating data references for varying flavors of
// runtime scenarios and vertex access types.
struct FDataReferenceCreatorBase
{
virtual ~ FDataReferenceCreatorBase ( ) = default ;
// Create a a new data reference for constructing operators
virtual FDataReference CreateDataReference ( const FOperatorSettings & InOperatorSettings ) const = 0 ;
// Create a data reference for constructing operators from a given data reference
virtual FPassThroughDataReference CreateDataReference ( const FAnyDataReference & InRef ) const
{
if constexpr ( bIsReferenceVertexAccess )
{
return InRef . GetDataReadReference < DataType > ( ) ;
}
else if constexpr ( bIsValueVertexAccess )
{
return InRef . GetDataValueReference < DataType > ( ) ;
}
else
{
static_assert ( " Unsupported EVertexAccessType " ) ;
}
}
} ;
// Create data references using a literal
struct FCreateWithLiteral : FDataReferenceCreatorBase
{
using FDataFactory = std : : conditional_t < bIsReferenceVertexAccess , TDataWriteReferenceLiteralFactory < DataType > , TDataValueReferenceLiteralFactory < DataType > > ;
FLiteral Literal ;
FCreateWithLiteral ( FLiteral & & InLiteral )
: Literal ( MoveTemp ( InLiteral ) )
{
}
virtual FDataReference CreateDataReference ( const FOperatorSettings & InOperatorSettings ) const override
{
return FDataFactory : : CreateExplicitArgs ( InOperatorSettings , Literal ) ;
}
} ;
// Create data references using a copy
struct FCreateWithCopy : FDataReferenceCreatorBase
{
using FDataFactory = std : : conditional_t < bIsReferenceVertexAccess , TDataWriteReferenceFactory < DataType > , TDataValueReferenceFactory < DataType > > ;
DataType Value ;
virtual FDataReference CreateDataReference ( const FOperatorSettings & InOperatorSettings ) const override
{
return FDataFactory : : CreateExplicitArgs ( InOperatorSettings , Value ) ;
}
} ;
2020-05-22 23:46:09 -04:00
2020-08-24 10:57:03 -04:00
public :
2020-05-22 23:46:09 -04:00
2022-06-02 10:50:07 -04:00
FInputNodeOperatorFactory ( const DataType & InValue )
: ReferenceCreator ( MakeUnique < FCreateWithCopy > ( InValue ) )
2020-05-22 23:46:09 -04:00
{
}
2022-06-02 10:50:07 -04:00
explicit FInputNodeOperatorFactory ( FLiteral & & InLiteral )
: ReferenceCreator ( MakeUnique < FCreateWithLiteral > ( MoveTemp ( InLiteral ) ) )
2020-07-20 00:05:22 -04:00
{
}
2022-06-02 10:50:07 -04:00
virtual TUniquePtr < IOperator > CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults ) override
2020-06-25 18:06:30 -04:00
{
2022-06-02 10:50:07 -04:00
using FInputNodeType = TInputNode < DataType , VertexAccess > ;
using FOwnedInputOperatorType = std : : conditional_t < bIsReferenceVertexAccess , TInputOperator < DataType > , FInputValueOperator > ;
using FPassThroughInputOperatorType = std : : conditional_t < bIsReferenceVertexAccess , TPassThroughOperator < DataType > , FInputValueOperator > ;
2020-06-25 18:06:30 -04:00
2022-06-02 10:50:07 -04:00
const FInputNodeType & InputNode = static_cast < const FInputNodeType & > ( InParams . Node ) ;
const FVertexName & VertexKey = InputNode . GetVertexName ( ) ;
2020-05-22 23:46:09 -04:00
2022-06-02 10:50:07 -04:00
if ( const FAnyDataReference * Ref = InParams . InputData . FindDataReference ( VertexKey ) )
{
// Pass through input value
return MakeUnique < FPassThroughInputOperatorType > ( VertexKey , ReferenceCreator - > CreateDataReference ( * Ref ) ) ;
}
else
{
// Owned input value
return MakeUnique < FOwnedInputOperatorType > ( VertexKey , ReferenceCreator - > CreateDataReference ( InParams . OperatorSettings ) ) ;
}
2020-05-22 23:46:09 -04:00
}
private :
2022-06-02 10:50:07 -04:00
TUniquePtr < FDataReferenceCreatorBase > ReferenceCreator ;
} ;
2020-05-22 23:46:09 -04:00
2022-06-02 10:50:07 -04:00
public :
// If true, this node can be instantiated by the Frontend.
static constexpr bool bCanRegister = bIsSupportedInput ;
static FVertexInterface DeclareVertexInterface ( const FVertexName & InVertexName )
{
return FVertexInterface (
FInputVertexInterface (
FInputDataVertex ( InVertexName , GetMetasoundDataTypeName < DataType > ( ) , FDataVertexMetadata { FText : : GetEmpty ( ) } , VertexAccess )
) ,
FOutputVertexInterface (
FOutputDataVertex ( InVertexName , GetMetasoundDataTypeName < DataType > ( ) , FDataVertexMetadata { FText : : GetEmpty ( ) } , VertexAccess )
)
) ;
}
static FNodeClassMetadata GetNodeInfo ( const FVertexName & InVertexName )
{
FNodeClassMetadata Info ;
Info . ClassName = { " Input " , GetMetasoundDataTypeName < DataType > ( ) , GetVariantName ( ) } ;
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
Info . Description = METASOUND_LOCTEXT ( " Metasound_InputNodeDescription " , " Input into the parent Metasound graph. " ) ;
Info . Author = PluginAuthor ;
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = DeclareVertexInterface ( InVertexName ) ;
return Info ;
}
template < typename . . . ArgTypes >
UE_DEPRECATED ( 5.1 , " Moved to internal implementation. " )
static FOperatorFactorySharedRef CreateOperatorFactoryWithArgs ( ArgTypes & & . . . Args )
{
using FCreatorType = FCreateDataReferenceWithCopy < DataType > ;
using FFactoryType = TInputOperatorFactory < DataType , FCreatorType > ;
return MakeOperatorFactoryRef < FFactoryType > ( FCreatorType ( Forward < ArgTypes > ( Args ) . . . ) ) ;
}
UE_DEPRECATED ( 5.1 , " Moved to internal implementation. " )
static FOperatorFactorySharedRef CreateOperatorFactoryWithLiteral ( FLiteral & & InLiteral )
{
using FCreatorType = FCreateDataReferenceWithLiteral < DataType > ;
using FFactoryType = TInputOperatorFactory < DataType , FCreatorType > ;
return MakeOperatorFactoryRef < FFactoryType > ( FCreatorType ( MoveTemp ( InLiteral ) ) ) ;
}
/* Construct a TInputNode using the TInputOperatorFactory<> and forwarding
* Args to the TInputOperatorFactory constructor . */
template < typename . . . ArgTypes >
UE_DEPRECATED ( 5.1 , " Constructing an TInputNode with args will no longer be supported. " )
TInputNode ( const FVertexName & InInstanceName , const FGuid & InInstanceID , const FVertexName & InVertexName , ArgTypes & & . . . Args )
: FNode ( InInstanceName , InInstanceID , GetNodeInfo ( InVertexName ) )
, VertexName ( InVertexName )
, Interface ( DeclareVertexInterface ( InVertexName ) )
, Factory ( MakeShared < FInputNodeOperatorFactory > ( Forward < ArgTypes > ( Args ) . . . ) )
{
}
/* Construct a TInputNode using the TInputOperatorLiteralFactory<> and moving
* InParam to the TInputOperatorLiteralFactory constructor . */
explicit TInputNode ( const FVertexName & InNodeName , const FGuid & InInstanceID , const FVertexName & InVertexName , FLiteral & & InParam )
: FNode ( InNodeName , InInstanceID , GetNodeInfo ( InVertexName ) )
, VertexName ( InVertexName )
, Interface ( DeclareVertexInterface ( InVertexName ) )
, Factory ( MakeShared < FInputNodeOperatorFactory > ( MoveTemp ( InParam ) ) )
{
}
const FVertexName & GetVertexName ( ) const
{
return VertexName ;
}
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 TSharedRef < IOperatorFactory , ESPMode : : ThreadSafe > GetDefaultOperatorFactory ( ) const override
{
return Factory ;
}
private :
FVertexName VertexName ;
FVertexInterface Interface ;
FOperatorFactorySharedRef Factory ;
2020-05-22 23:46:09 -04:00
} ;
2020-11-04 14:26:37 -04:00
2021-05-20 19:33:21 -04:00
template < typename DataType , typename ReferenceCreatorType >
2022-05-19 14:18:38 -04:00
TUniquePtr < IOperator > TInputOperatorFactory < DataType , ReferenceCreatorType > : : CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults )
2020-11-04 14:26:37 -04:00
{
using FInputNodeType = TInputNode < DataType > ;
const FInputNodeType & InputNode = static_cast < const FInputNodeType & > ( InParams . Node ) ;
2021-09-13 14:13:39 -04:00
const FVertexName & VertexKey = InputNode . GetVertexName ( ) ;
2020-11-04 14:26:37 -04:00
2022-05-19 14:18:38 -04:00
if ( InParams . InputData . IsVertexBound ( VertexKey ) )
2021-05-20 19:33:21 -04:00
{
// Data is externally owned. Use pass through operator
2022-06-02 10:50:07 -04:00
TDataReadReference < DataType > DataRef = InParams . InputData . GetDataReadReference < DataType > ( VertexKey ) ;
2021-05-20 19:33:21 -04:00
return MakeUnique < TPassThroughOperator < DataType > > ( InputNode . GetVertexName ( ) , DataRef ) ;
}
else
{
// Create write reference by calling compatible constructor with literal.
2022-06-02 10:50:07 -04:00
TDataWriteReference < DataType > DataRef = ReferenceCreator . CreateDataReference ( InParams . OperatorSettings ) ;
2021-05-20 19:33:21 -04:00
return MakeUnique < TInputOperator < DataType > > ( InputNode . GetVertexName ( ) , DataRef ) ;
}
2020-11-04 14:26:37 -04:00
}
2020-07-22 14:52:03 -04:00
} // namespace Metasound
2021-05-28 14:09:45 -04:00
# undef LOCTEXT_NAMESPACE // MetasoundFrontend