// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Internationalization/Text.h" #include "MetasoundOperatorInterface.h" #include "MetasoundNodeInterface.h" #define LOCTEXT_NAMESPACE "MetasoundGraphCore" namespace Metasound { /** TInputOperator supplies a writable input and a readable output. */ template class TInputOperator : public IOperator { public: using FDataWriteReference = TDataWriteReference; TInputOperator(const FString& InDataReferenceName, FDataWriteReference InDataReference) { Inputs.AddDataWriteReference(InDataReferenceName, InDataReference); Outputs.AddDataReadReference(InDataReferenceName, InDataReference); } virtual ~TInputOperator() {} virtual FDataReferenceCollection GetInputs() const override { return Inputs; } virtual FDataReferenceCollection GetOutputs() const override { return Outputs; } virtual FExecuteFunction GetExecuteFunction() override { return nullptr; } private: FDataReferenceCollection Outputs; FDataReferenceCollection Inputs; }; /** TInputOperatorLiteralFactory creates an input by passing it a literal. */ template class TInputOperatorLiteralFactory : public IOperatorFactory { public: // 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 bCanRegister = TLiteralTraits::bIsParsableFromAnyLiteralType; using FDataWriteReference = TDataWriteReference; TInputOperatorLiteralFactory(FLiteral&& InInitParam) : InitParam(MoveTemp(InInitParam)) { } virtual TUniquePtr CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors) override; private: FLiteral InitParam; }; /** TInputOperatorFactory initializes the DataType at construction. It uses * the DataType's copy operator to create additional version. */ template class TInputOperatorFactory : public IOperatorFactory { public: using FDataWriteReference = TDataWriteReference; template TInputOperatorFactory(ArgTypes&&... Args) : Data(Forward(Args)...) { } virtual TUniquePtr CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors) override; private: DataType Data; }; /** TInputNode represents an input to a metasound graph. */ template class TInputNode : public FNode { public: // If true, this node can be instantiated by the FrontEnd. static constexpr bool bCanRegister = TInputOperatorLiteralFactory::bCanRegister; static FVertexInterface DeclareVertexInterface(const FString& InVertexName) { return FVertexInterface( FInputVertexInterface( TInputDataVertexModel(InVertexName, FText::GetEmpty()) ), FOutputVertexInterface( TOutputDataVertexModel(InVertexName, FText::GetEmpty()) ) ); } static FNodeClassMetadata GetNodeInfo(const FString& InVertexName) { FNodeClassMetadata Info; Info.ClassName = {TEXT("Input"), GetMetasoundDataTypeName(), TEXT("")}; Info.MajorVersion = 1; Info.MinorVersion = 0; Info.DisplayName = FText::Format(LOCTEXT("Metasound_InputNodeDisplayNameFormat", "Input {0}"), FText::FromName(GetMetasoundDataTypeName())); Info.Description = LOCTEXT("Metasound_InputNodeDescription", "Input into the parent Metasound graph."); Info.Author = PluginAuthor; Info.PromptIfMissing = PluginNodeMissingPrompt; Info.DefaultInterface = DeclareVertexInterface(InVertexName); return Info; } /* Construct a TInputNode using the TInputOperatorFactory<> and forwarding * Args to the TInputOperatorFactory constructor.*/ template TInputNode(const FString& InNodeDescription, const FGuid& InInstanceID, const FString& InVertexName, ArgTypes&&... Args) : FNode(InNodeDescription, InInstanceID, GetNodeInfo(InVertexName)) , VertexName(InVertexName) , Interface(DeclareVertexInterface(InVertexName)) , Factory(MakeOperatorFactoryRef>(Forward(Args)...)) { } /* Construct a TInputNode using the TInputOperatorLiteralFactory<> and moving * InParam to the TInputOperatorLiteralFactory constructor.*/ explicit TInputNode(const FString& InNodeDescription, const FGuid& InInstanceID, const FString& InVertexName, FLiteral&& InParam) : FNode(InNodeDescription, InInstanceID, GetNodeInfo(InVertexName)) , VertexName(InVertexName) , Interface(DeclareVertexInterface(InVertexName)) , Factory(MakeOperatorFactoryRef>(MoveTemp(InParam))) { } const FString& 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 GetDefaultOperatorFactory() const override { return Factory; } private: FString VertexName; FVertexInterface Interface; FOperatorFactorySharedRef Factory; }; template TUniquePtr TInputOperatorLiteralFactory::CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors) { using FInputNodeType = TInputNode; // Create write reference by calling compatible constructor with literal. FDataWriteReference DataRef = TDataWriteReferenceLiteralFactory::CreateExplicitArgs(InParams.OperatorSettings, InitParam); const FInputNodeType& InputNode = static_cast(InParams.Node); return MakeUnique>(InputNode.GetVertexName(), DataRef); } template TUniquePtr TInputOperatorFactory::CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors) { using FInputNodeType = TInputNode; // Create write reference by calling copy constructor. FDataWriteReference DataRef = TDataWriteReferenceFactory::CreateExplicitArgs(InParams.OperatorSettings, Data); const FInputNodeType& InputNode = static_cast(InParams.Node); return MakeUnique>(InputNode.GetVertexName(), DataRef); } } // namespace Metasound #undef LOCTEXT_NAMESPACE //MetasoundOutputNode